text:
# m5_1s.jl

using Pkg, DrWatson

using MonteCarloMeasurements
using StanQuap
using StatisticalRethinking

df = CSV.read(sr_datadir("WaffleDivorce.csv"), DataFrame);
scale!(df, [:Marriage, :MedianAgeMarriage, :Divorce])

stan5_1 = "
data {
    int < lower = 1 > N; // Sample size
    vector[N] D; // Outcome
    vector[N] A; // Predictor
}

parameters {
    real a; // Intercept
    real bA; // Slope (regression coefficients)
    real < lower = 0 > sigma;    // Error SD
}

model {
    vector[N] mu;               // mu is a vector
    a ~ normal(0, 0.2);         //Priors
    bA ~ normal(0, 0.5);
    sigma ~ exponential(1);
    mu = a + bA * A;
    D ~ normal(mu , sigma);     // Likelihood
}
";

data = (N=size(df, 1), D=df.Divorce_s, A=df.MedianAgeMarriage_s)
init = (a=1.0, bA=1.0, sigma=10.0)
q5_1s, m5_1s, o5_1s = stan_quap("m5.2s", stan5_1; data, init);

if !isnothing(m5_1s)
  part5_1s = read_samples(m5_1s, :particles)
end

if !isnothing(q5_1s)
  quap5_1s_df = sample(q5_1s)
  precis(quap5_1s_df)
end


text:
function editDistance(s1, s2)
    m=length(s1)+1
    n=length(s2)+1
    i=0
    j=0
    tbl = Dict{Tuple{Int64,Int64},Int64}()
    for i=1:m
        tbl[i,1]=i-1
    end
    for j=1:n
        tbl[1,j]=j-1
    end
    for i=2:m
        for j=2:n
            cost = s1[i-1] == s2[j-1]?0:1
            tbl[i,j] = min(tbl[i, j-1]+1, tbl[i-1, j]+1, tbl[i-1, j-1]+cost)
        end
    end
    tbl[i,j]
end

d=-1
for i=1:1000000
    d=editDistance("AAAATTTTCCCCGGGGAAAANTTTTCCCCGGGG", "AAAATTTTCCCCGGGGAAAAMTTTTCCCCGGGG")
end
println(d)

ext: jl


text:
function f(x::Array{Float64,2})
  x[1]^2 + x[2]^2
end
function gradient(x::Array{Float64,2})
  [2*x[1] 2*x[2]]
end

# Initial conditions
x0 = [0.0 0.0]

# Tuning parameters
epsilon = .001  # step size
L = 10          # number of steps

# Basic tests on regular interface
x,gx = hmc_sampler(x0, f, gradient, epsilon, L)

@assert isa(x,Array{Float64,2})
@assert isa(gx,Float64)

# Basic tests on Density interface
dd = DifferentiableDensity(f,gradient)
x,gx = hmc_sampler(x0, dd, epsilon, L)

@assert isa(x,Array{Float64,2})
@assert isa(gx,Float64)

# Example of using Options with an HMC sampler allowing bounds
opts = Options(:stepsize,0.01,
               :numsteps,int(50),
               :bounded,[1],          # list of dimensions that are bounded
               :lower_bounds,[0],  # lower bound for 1st dim
               :upper_bounds,[Inf])   # upper bound for 1st dim
x,gx = bounded_hmc_sampler(x0, dd, opts)

@assert isa(x,Array{Float64,2})
@assert isa(gx,Float64)
@assert x[1] > 0


text:
using GeometryTypes
using SurfaceTopology
using LinearAlgebra

function quadraticform(vects,vnormal)

    Lx = [0 0 0; 0 0 -1; 0 1 0]
    Ly = [0 0 1; 0 0 0; -1 0 0]
    Lz = [0 -1 0; 1 0 0; 0 0 0]

    d = [0,0,1] + vnormal
    d /= norm(d)

    Ln = d[1]*Lx + d[2]*Ly + d[3]*Lz
    R = exp(pi*Ln)

    vects = copy(vects)
    for vj in 1:length(vects)
        vects[vj] = R*vects[vj]
    end

    ### Construction of the system
    A = Array{Float64}(undef,3,3)
    B = Array{Float64}(undef,3)

    vects_norm2 = Array{Float64}(undef,length(vects))
    for vj in 1:length(vects)
       vects_norm2[vj] = norm(vects[vj])^2
    end

    A[1,1] = sum((v[1]^4 for v in vects) ./ vects_norm2)
    A[1,2] = sum((v[1]^3*v[2] for v in vects) ./ vects_norm2)
    A[1,3] = sum((v[1]^2*v[2]^2 for v in vects) ./ vects_norm2)
    A[2,1] = A[1,2]
    A[2,2] = A[1,3]
    A[2,3] = sum( (v[2]^3*v[1] for v in vects) ./vects_norm2)
    A[3,1] = A[1,3]
    A[3,2] = A[2,3]
    A[3,3] = sum((v[2]^4 for v in vects) ./vects_norm2)

    B[1] = sum((v[3]*v[1]^2 for v in vects) ./vects_norm2)
    B[2] = sum((v[1]*v[2]*v[3] for v in vects) ./vects_norm2)
    B[3] = sum((v[2]^2*v[3] for v in vects) ./vects_norm2)

    C,D,E = A\B
    return C,D,E
end

function meancurvature(points,topology)
    curvatures = Array{Float64}(undef,length(points))
    for v in 1:length(points)

        s = Point(0,0,0)
        for (v1,v2) in EdgeRing(v,topology)
            s += cross(points[v2],points[v1])
        end
        normal = s ./ norm(s)

        vring = collect(VertexRing(v,topology))
        vects = [points[vi] - points[v] for vi in vring]

        C,D,E = quadraticform(vects,normal)

        A = [C D/2;D/2 E]
        k1,k2 = eigvals(-A)
        H = (k1 + k2)/2

        ### Multiplier by is 2 an empirical fix
        curvatures[v] = 2*H
    end
    return curvatures
end

function normals(vertices,topology)
    n = Point{3,Float64}[]
    for v in 1:length(vertices)
        s = Point(0,0,0)
        for (v1,v2) in EdgeRing(v,topology)
            s += cross(vertices[v2],vertices[v1])
        end
        normal = s ./ norm(s)
        push!(n,normal)
    end
    return n
end

function vertexareas(points,topology)
    vareas = zeros(Float64,length(points))
    for face in Faces(topology)
        v1,v2,v3 = face
        area = norm(cross(points[v2]-points[v1],points[v3]-points[v1])) /2
        vareas[v1] += area/3
        vareas[v2] += area/3
        vareas[v3] += area/3
    end
    return vareas
end

function surfacevolume(points,topology)
    # Calculate face normal
    # Calculate projected area
    # Calculate ordinary volume
    # Calculate volume between projected and real area
    # (+) if normal is outwards

    normal0 = [0,0,1]
    s = 0
    for face in Faces(topology)
        y1 = points[face[1]]
        y2 = points[face[2]]
        y3 = points[face[3]]

        normaly = cross(y2-y1,y3-y1)
        normaly /= norm(normaly)

        area = norm(cross(y2-y1,y3-y1))/2
        areaproj = dot(normaly,normal0)*area
        volume = dot(y1 + y2 + y3,normal0)/3*areaproj

        s += volume
    end

    return s
end


text:
using DashBootstrapComponents

fade = html_div([
    dbc_button(
        "Toggle fade",
        id = "fade-transition-button",
        className = "mb-3",
        n_clicks = 0,
    ),
    dbc_fade(
        dbc_card(
            dbc_cardbody(html_p("This content fades in and out", className = "card-text")),
        ),
        id = "fade-transition",
        is_in = true,
        style = Dict("transition" => "opacity 2000ms ease"),
        timeout = 2000,
    ),
]);

callback!(
    app,
    Output("fade-transition", "is_in"),
    Input("fade-transition-button", "n_clicks"),
    State("fade-transition", "is_in"),
) do n, is_in
    return n > 0 ? is_in == 0 : true
end;

max_issues_repo_name: sthagen/dash-bootstrap-components

max_forks_repo_name: sthagen/dash-bootstrap-components


text:
import Bijections

BRACKET_PAIRS = Bijections.Bijection(Dict{Char, Char}('(' => ')', '[' => ']',
                                                      '{' => '}', '<' => '>'))

function part1_and_2(fname)
  corrupt_score = 0
  autocomplete_score = Vector{Int}()
  open(fname, "r") do f
    data = readlines(f)
    for line in data
      score = analyse_line(line)
      if score > 0
        push!(autocomplete_score, score)
      else
        corrupt_score += score
      end
    end
  end
  corrupt_score = abs(corrupt_score)
  middle_idx = Int(floor(length(autocomplete_score)/2) + 1)
  autocomplete_result = sort(autocomplete_score)[middle_idx]
  println("Total corruption score is $corrupt_score")
  println("Autocomplete score $autocomplete_result")
end

function analyse_line(line)
  penalties = Dict{Char, Int}(')' => 3, ']' => 57, '}' => 1197, '>' => 25137)
  to_be_closed = Vector{Char}()
  for character in line
    if character in Bijections.domain(BRACKET_PAIRS)
      push!(to_be_closed, character)
    elseif character != BRACKET_PAIRS[to_be_closed[end]]
      return -penalties[character]
    else
      pop!(to_be_closed)
    end
  end

  autocomplete_score = Dict{Char, Int}(')' => 1, ']' => 2, '}' => 3, '>' => 4)
  score = 0
  while !isempty(to_be_closed)
    score *= 5
    score += autocomplete_score[BRACKET_PAIRS[to_be_closed[end]]]
    pop!(to_be_closed)
  end
  return score
end

part1_and_2("test_input.txt")
part1_and_2("input.txt")


text:
import Pkg
Pkg.add("PyCall")

using PyCall

# numpy and lightonopu need be installed in Python
lgopu = pyimport("lightonopu")
np = pyimport("numpy")

# return a Julia Array
x = np.random.randint(0, 2, size=(3000, 912*1140), dtype=np.uint8)

# initialize OPU object
opu = lgopu.OPU(n_components=10000)

# perform the optical processing
y = opu.transform1d(x)

# alternative
y = @pycall opu.transform1d(x::Array)::PyArray

# check output properties
println(typeof(y))
println(ndims(y))
println(minimum(y), " ", maximum(y))

max_stars_repo_name: lightonai/gists

max_issues_repo_name: lightonai/gists

max_forks_repo_name: lightonai/gists


text:
using HttpServer
using Meddle

include("../ServeStatic.jl")

stack = middleware(URLDecoder, ServeStatic("test/fixtures"))
http = HttpHandler((req, res) ->
	Meddle.handle(stack, MeddleRequest(req, Dict(), Dict()), res))

http.events["error"] = (client, err) -> println(err)
http.events["listen"] = (port) -> println("Listening on $port...")

server = Server(http)
run(server, 8084)


text:
using SeisPlots
using Test

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


text:
using PyCallChainRules.Torch: TorchModuleWrapper, torch, functorch, dlpack, pyto_dlpack, pyfrom_dlpack, ispysetup

using Test
using Zygote
using Flux
using FillArrays
using ChainRulesCore: NoTangent, AbstractZero
import Random
using PyCall
using CUDA
using DLPack
using Functors: fmap

if !ispysetup[]
    return
end

if CUDA.functional()
    device = torch.device("cuda:0")
else
    device = torch.device("cpu")
end

function compare_grad_wrt_params(modelwrap, inputs...)
    params = map(x -> DLPack.share(x, PyObject, pyfrom_dlpack).to(device = device, dtype = modelwrap.dtype).requires_grad_(true), (modelwrap.params))
    torch_out = modelwrap.torch_stateless_module(params, modelwrap.buffers, fmap(z->DLPack.share(z, PyObject, pyfrom_dlpack).to(dtype=modelwrap.dtype, device=device), inputs)...).sum()
    torchgrad = map(x-> (x.cpu().numpy()), torch.autograd.grad(torch_out, params))
    grad,  = Zygote.gradient(m->sum(m(inputs...)), modelwrap)
    @test length(torchgrad) == length(grad.params)
    for i in 1:length(grad.params)
        @test isapprox(sum(torchgrad[i]), sum(grad.params[i]))
    end
    @test length(grad.params) == length(modelwrap.params)
    @test grad.params[1] !== nothing
    @test grad.params[2] !== nothing
    @test size(grad.params[1]) == size(modelwrap.params[1])
    @test size(grad.params[2]) == size(modelwrap.params[2])
end

function compare_grad_wrt_inputs(modelwrap, x)
    params = map(z -> DLPack.share(z, PyObject, pyfrom_dlpack).to(device = device, dtype = modelwrap.dtype).requires_grad_(true), (modelwrap.params))
    xtorch = DLPack.share(copy(x), PyObject, pyfrom_dlpack).to(dtype=modelwrap.dtype, device=device).requires_grad_(true)
    torch_out = modelwrap.torch_stateless_module(params, modelwrap.buffers, xtorch).sum()
    torchgrad = map(z-> (copy(z.cpu().numpy())), torch.autograd.grad(torch_out, xtorch))[1]
    grad, = Zygote.gradient(z->sum(modelwrap(z)), x)
    @test size(grad) == size(x)
    @test length(torchgrad) == length(grad)
    @test isapprox(sum(torchgrad), sum(grad))
end

@testset "dlpack" begin
    for dims in ((10,), (1, 10), (2, 3, 5), (2, 3, 4, 5))
        xto = torch.randn(dims..., device=device)
        xjl = DLPack.wrap(xto, pyto_dlpack)
        @test Tuple(xto.size()) == reverse(size(xjl))
        @test isapprox(sum(xto.cpu().numpy()), sum(xjl))
    end
end

batchsize = 1
indim = 3
outdim = 2
hiddendim = 4

@testset "linear" begin
    lin = torch.nn.Linear(indim, outdim).to(device=device)
    linwrap = TorchModuleWrapper(lin)
    if CUDA.functional()
        linwrap = fmap(CUDA.cu, linwrap)
    end
    x = randn(Float32, indim, batchsize)
    if CUDA.functional()
        x = cu(x)
    end
    y = linwrap(x)
    @test size(y) == (outdim, batchsize)
    compare_grad_wrt_params(linwrap, x)
    compare_grad_wrt_inputs(linwrap, x)

end

@testset "mlp" begin
    mlp = torch.nn.Sequential(torch.nn.Linear(indim, hiddendim), torch.nn.ReLU(), torch.nn.Linear(hiddendim, outdim)).to(device=device)
    mlpwrap = TorchModuleWrapper(mlp)
    if CUDA.functional()
        mlpwrap = fmap(CUDA.cu, mlpwrap)
    end

    x = randn(Float32, indim, batchsize)
    if CUDA.functional()
        x = cu(x)
    end
    y = mlpwrap(x)
    @test size(y) == (outdim, batchsize)
    compare_grad_wrt_params(mlpwrap, x)
    compare_grad_wrt_inputs(mlpwrap, x)
end

# Flux check
@testset "flux" begin
    lin = torch.nn.Linear(indim, outdim).to(device=device)
    linwrap = TorchModuleWrapper(lin)
    nn = Chain(Dense(4, 3), linwrap)
    if CUDA.functional()
        nn = Flux.gpu(nn)
    end
    x2 = randn(Float32, 4, batchsize)
    if CUDA.functional()
        x2 = cu(x2)
    end
    grad,  = Zygote.gradient(m->sum(m(x2)), nn)
    @test grad !== nothing
end

@testset "conv" begin
    model = torch.nn.Sequential(
            torch.nn.Conv2d(1,2,5),
            torch.nn.ReLU(),
            torch.nn.Conv2d(2,6,5),
            torch.nn.ReLU()
            ).to(device=device)
    modelwrap = TorchModuleWrapper(model)
    if CUDA.functional()
        modelwrap = fmap(CUDA.cu, modelwrap)
    end
    input = randn(Float32, 12, 12, 1, batchsize)
    if CUDA.functional()
        input = cu(input)
    end
    output = modelwrap(input)

    compare_grad_wrt_params(modelwrap, input)
    compare_grad_wrt_inputs(modelwrap, input)
end

@testset "cpu" begin
    dev = torch.device("cpu")
    indim = 32
    outdim = 16
    torch_module = torch.nn.Linear(indim, outdim).to(device=dev) # Can be anything subclassing torch.nn.Module
    jlwrap = TorchModuleWrapper(torch_module)

    batchsize = 64
    input = randn(Float32, indim, batchsize)
    output = jlwrap(input)

    target = randn(Float32, outdim, batchsize)
    loss(m, x, y) = sum(m(x) .- target)
    grad, = Zygote.gradient(m->loss(m, input, target), jlwrap)
    @test grad.params !== nothing
end

py"""
import torch
class CustomModuleTupleout(torch.nn.Module):
    def __init__(self):
        super().__init__()
        self.lin1 = torch.nn.Linear(16, 4)
        self.lin2 = torch.nn.Linear(3, 4)

    def forward(self, x, y):
        return self.lin1(x), self.lin2(y)
"""
@testset "multi_io" begin
    model = py"CustomModuleTupleout"().to(device=torch.device("cpu"))
    modelwrap = TorchModuleWrapper(model)

    in1 = randn(Float32, 16, batchsize)
    in2 = randn(Float32, 3, batchsize)
    x = (in1, in2)
    output = modelwrap(x...)
    @test length(output) == 2
    grad,  = Zygote.gradient(m->sum(sum(m(x...))), modelwrap)
    @test grad.params !== nothing
end

# https://github.com/JuliaPy/PyCall.jl/issues/175
# py"""
# import torch
# class CustomModule(torch.nn.Module):
#     def __init__(self):
#         super().__init__()
#         self.lin = torch.nn.Linear(16, 4)

#     def forward(self, x):
#         return self.lin(x.input)
# """

# @testset "nametupleinput" begin
#     model = py"CustomModule"().to(device=torch.device("cpu"))
#     modelwrap = TorchModuleWrapper(model)

#     in = randn(Float32, 16, batchsize)
#     x = (;input=in)
#     output = modelwrap(x)
#     grad,  = Zygote.gradient(m->sum(m(x)), modelwrap)
#     @show grad
# end


text:
using BasisFunctions: hasderivative, hasantiderivative, resize

P = 80

@testset "$(rpad("Bernstein polynomials",P))" begin

    ξ = [0.0, 1.0]
    b = Bernstein(ξ)

    BasisFunctions.Test.test_generic_dict_interface(Bernstein(10))

    @testset "$(rpad("Basic functionality",P))" begin
        @test nodes(b) == ξ
        @test nnodes(b) == 2
        @test degree(b) == 1
        @test support(b) == BernsteinInterval{eltype(ξ)}()
        @test nodes(b) == nodes(similar(b, eltype(ξ), 2))
        @test nodes(b) == nodes(similar(b, eltype(ξ), ξ))
        @test nodes(resize(b, 2)) == ξ
        @test nodes(resize(b, 5)) == [0.0, 0.25, 0.50, 0.75, 1.0]
    end

    @testset "$(rpad("Basis evaluation",P))" begin
        @test b[1](0.0) == 1.0
        @test b[1](0.5) == 0.5
        @test b[1](1.0) == 0.0

        @test b[2](0.0) == 0.0
        @test b[2](0.5) == 0.5
        @test b[2](1.0) == 1.0
    end

    @testset "$(rpad("Basis derivative",P))" begin
        @test eval_element_derivative(b, 1, 0.0) == -1.0
        @test eval_element_derivative(b, 1, 0.5) == -1.0
        @test eval_element_derivative(b, 1, 1.0) == -1.0

        @test eval_element_derivative(b, 2, 0.0) == +1.0
        @test eval_element_derivative(b, 2, 0.5) == +1.0
        @test eval_element_derivative(b, 2, 1.0) == +1.0
    end

end


text:
module PCA
    using Pluto

    run_notebook() = Pluto.run(notebook=joinpath(@__DIR__, "../notebook/pca.jl"))
end


text:
function AuxiliaryElements(arg0::Orbit, arg1::jint)
    return AuxiliaryElements((Orbit, jint), arg0, arg1)
end

function equals(obj::Object, arg0::Object)
    return jcall(obj, "equals", jboolean, (Object,), arg0)
end

function get_alpha(obj::AuxiliaryElements)
    return jcall(obj, "getAlpha", jdouble, ())
end

function get_b(obj::AuxiliaryElements)
    return jcall(obj, "getB", jdouble, ())
end

function get_beta(obj::AuxiliaryElements)
    return jcall(obj, "getBeta", jdouble, ())
end

function get_c(obj::AuxiliaryElements)
    return jcall(obj, "getC", jdouble, ())
end

function get_class(obj::Object)
    return jcall(obj, "getClass", Class, ())
end

function get_date(obj::AuxiliaryElements)
    return jcall(obj, "getDate", AbsoluteDate, ())
end

function get_ecc(obj::AuxiliaryElements)
    return jcall(obj, "getEcc", jdouble, ())
end

function get_frame(obj::AuxiliaryElements)
    return jcall(obj, "getFrame", Frame, ())
end

function get_gamma(obj::AuxiliaryElements)
    return jcall(obj, "getGamma", jdouble, ())
end

function get_h(obj::AuxiliaryElements)
    return jcall(obj, "getH", jdouble, ())
end

function get_k(obj::AuxiliaryElements)
    return jcall(obj, "getK", jdouble, ())
end

function get_keplerian_period(obj::AuxiliaryElements)
    return jcall(obj, "getKeplerianPeriod", jdouble, ())
end

function get_lf(obj::AuxiliaryElements)
    return jcall(obj, "getLf", jdouble, ())
end

function get_lm(obj::AuxiliaryElements)
    return jcall(obj, "getLM", jdouble, ())
end

function get_lv(obj::AuxiliaryElements)
    return jcall(obj, "getLv", jdouble, ())
end

function get_mean_motion(obj::AuxiliaryElements)
    return jcall(obj, "getMeanMotion", jdouble, ())
end

function get_p(obj::AuxiliaryElements)
    return jcall(obj, "getP", jdouble, ())
end

function get_q(obj::AuxiliaryElements)
    return jcall(obj, "getQ", jdouble, ())
end

function get_retrograde_factor(obj::AuxiliaryElements)
    return jcall(obj, "getRetrogradeFactor", jint, ())
end

function get_sma(obj::AuxiliaryElements)
    return jcall(obj, "getSma", jdouble, ())
end

function get_vector_f(obj::AuxiliaryElements)
    return jcall(obj, "getVectorF", Vector3D, ())
end

function get_vector_g(obj::AuxiliaryElements)
    return jcall(obj, "getVectorG", Vector3D, ())
end

function get_vector_w(obj::AuxiliaryElements)
    return jcall(obj, "getVectorW", Vector3D, ())
end

function hash_code(obj::Object)
    return jcall(obj, "hashCode", jint, ())
end

function notify(obj::Object)
    return jcall(obj, "notify", void, ())
end

function notify_all(obj::Object)
    return jcall(obj, "notifyAll", void, ())
end

function to_string(obj::Object)
    return jcall(obj, "toString", JString, ())
end

function wait(obj::Object)
    return jcall(obj, "wait", void, ())
end

function wait(obj::Object, arg0::jlong)
    return jcall(obj, "wait", void, (jlong,), arg0)
end

function wait(obj::Object, arg0::jlong, arg1::jint)
    return jcall(obj, "wait", void, (jlong, jint), arg0, arg1)
end


text:
export Adam, update!

mutable struct Adam{ T } <: Optimizer
    x    :: T
    s    :: T
    r    :: T
    shat :: T
    rhat :: T
    ρ1   :: Float64
    ρ2   :: Float64
    λ    :: Float64
    it   :: Int64
    tmp  :: T
end

function Adam(x::Vector{Float64}; ρ1::Float64=0.9, ρ2::Float64=0.999, λ::Float64=1e-8)
    return Adam(x, zeros(Float64, size(x)), zeros(Float64, size(x)), zeros(Float64, size(x)), zeros(Float64, size(x)), ρ1, ρ2, λ, 1, zeros(Float64, size(x)))
end

function Adam(x::T; ρ1::Float64=0.9, ρ2::Float64=0.999, λ::Float64=1e-8) where { T <: Real }
    return Adam(float(x), 0.0, 0.0, 0.0, 0.0, ρ1, ρ2, λ, 1, 0.0)
end

getx(optimizer::Adam)       = return optimizer.x
gets(optimizer::Adam)       = return optimizer.s
getr(optimizer::Adam)       = return optimizer.r
getshat(optimizer::Adam)    = return optimizer.shat
getrhat(optimizer::Adam)    = return optimizer.rhat
getρ1(optimizer::Adam)      = return optimizer.ρ1
getρ2(optimizer::Adam)      = return optimizer.ρ2
getλ(optimizer::Adam)       = return optimizer.λ
getit(optimizer::Adam)      = return optimizer.it
getall(optimizer::Adam)     = return optimizer.x, optimizer.s, optimizer.r, optimizer.shat, optimizer.rhat, optimizer.ρ1, optimizer.ρ2, optimizer.λ, optimizer.it, optimizer.tmp

function setx!(optimizer::Adam{T}, x::T) where { T <: Real }
    optimizer.x = x
end
function setx!(optimizer::Adam{T}, x::T) where { T <: AbstractArray }
    optimizer.x .= x
end

function sets!(optimizer::Adam{T}, s::T) where { T <: Real }
    optimizer.s = s
end
function sets!(optimizer::Adam{T}, s::T) where { T <: AbstractArray }
    optimizer.s .= s
end

function setr!(optimizer::Adam{T}, r::T) where { T <: Real }
    optimizer.r = r
end
function setr!(optimizer::Adam{T}, r::T) where { T <: AbstractArray }
    optimizer.r .= r
end

function setshat!(optimizer::Adam{T}, shat::T) where { T <: Real }
    optimizer.shat = shat
end
function setshat!(optimizer::Adam{T}, shat::T) where { T <: AbstractArray }
    optimizer.shat .= shat
end

function setrhat!(optimizer::Adam{T}, rhat::T) where { T <: Real }
    optimizer.rhat = rhat
end
function setrhat!(optimizer::Adam{T}, rhat::T) where { T <: AbstractArray }
    optimizer.rhat .= rhat
end

function setρ1!(optimizer::Adam{T}, ρ1::Float64) where { T }
    optimizer.ρ1 = ρ1
end

function setρ2!(optimizer::Adam{T}, ρ2::Float64) where { T }
    optimizer.ρ2 = ρ2
end

function setλ!(optimizer::Adam{T}, λ::Float64) where { T }
    optimizer.λ = λ
end

function setit!(optimizer::Adam{T}, it::Int64) where { T }
    optimizer.it = it
end

function update!(optimizer::Adam{ T }, ∇::T) where { T <: Real }

    # fetch parameters
    x, s, r, _, _, ρ1, ρ2, λ, it, tmp = getall(optimizer)

    # update (biased) first moment
    s *= ρ1
    tmp = ∇
    tmp *= (1-ρ1)
    s += tmp
    sets!(optimizer, s)

    # update (unbiased) first moment
    shat = s / (1 - ρ1^it)

    # update (biased) second moment
    r *= ρ2
    tmp = ∇
    tmp ^= 2
    tmp *= (1-ρ2)
    r += tmp
    setr!(optimizer, r)

    # update (unbiased) second moment
    rhat = r / (1 - ρ2^it)

    # perform accelerated gradient step
    rhat = sqrt(rhat)
    rhat += 1e-20
    rhat /= λ
    shat /= rhat
    x -= shat
    setx!(optimizer, x)

    # update iteration count
    setit!(optimizer, it + 1)

end

function update!(optimizer::Adam{ T }, ∇::T) where { T <: AbstractArray }

    # fetch parameters
    x, s, r, shat, rhat, ρ1, ρ2, λ, it, tmp = getall(optimizer)

    # update (biased) first moment
    s .*= ρ1
    tmp .= ∇
    tmp .*= (1-ρ1)
    s .+= tmp

    # update (unbiased) first moment
    shat .= s
    shat ./= (1 - ρ1^it)

    # update (biased) second moment
    r .*= ρ2
    tmp .= ∇
    tmp .^= 2
    tmp .*= (1-ρ2)
    r .+= tmp

    # update (unbiased) second moment
    rhat .= r
    rhat ./= (1 - ρ2^it)

    # perform accelerated gradient step
    tmp .= sqrt.(rhat)
    tmp .+= 1e-20
    tmp ./= λ
    shat ./= tmp
    x .-= shat

    # update iteration count
    setit!(optimizer, it + 1)

end


text:
"""
    function get_PTDF_thermal_bindingPg(args... ;kwargs...)

Identify generators which Active Power is binding (Skips Slack), locate their buses and
return the corresponding PTDF matrix

# Arguments
- `sys::System`:                            Power system in p.u. (from PowerSystems.jl)
- `res::PowerSimulations.
    OperationsProblemResults`:              Results of the solved OPF for the system
                                             (from PowerSimulations.jl)
- `PTDF_matrix::Any`:                       PTDF matrix as a direct output from
                                            PTDF_matrix = PTDF(sys), see PowerSystems.jl

# Keywords
- `dual_gen_tol::Float64 = 1e-1`:           Tolerance to identify any binding generators

# Throws
- `ERROR`:                                  PTDF_matrix has no field data. The argument must
                                            be a direct output from PTDF_matrix = PTDF(sys)
                                            see PowerSystems.jl
"""
function get_PTDF_thermal_bindingPg(
    sys::System,
    res::PowerSimulations.OperationsProblemResults,
    PTDF_matrix ::Array;
    dual_gen_tol::Float64 = 1e-1
    )
    # Define elements
    gen_loc = 0
    gen_bindPg = 0 #number of gen binding (start of counter)
    gens_thermal_bindPg_busnumber = Array{Int64}(undef,0)
    gens_thermal_bindPg_name = Array{String}(undef,0)
    (nl,nb)=size(PTDF_matrix)
    PTDF_bindingPg = Array{Float64}(undef,(nl,0))

    # Get all thermal Generators
    gens_thermal = get_components(ThermalStandard, sys)

    # Get dual variables from the OPF results
    dualPgub = get_duals(res)[:P_ub__ThermalStandard__RangeConstraint]
    dualPglb = get_duals(res)[:P_lb__ThermalStandard__RangeConstraint]

    # Identify Generators and Locate their Buses
    for gen_thermal in gens_thermal
        gen_loc = gen_loc +1
        if get_bustype(gen_thermal.bus) ≠ BusTypes.REF  #skips slack
            bindub = !isapprox(dualPgub[1,gen_loc],0.0; atol = dual_gen_tol) #is binding?
            bindlb = !isapprox(dualPglb[1,gen_loc],0.0; atol = dual_gen_tol) #is binding?
            if  bindub || bindlb #if binding dual is !≈  0.0 then
                gen_bindPg = gen_bindPg +1
                resize!(gens_thermal_bindPg_name,gen_bindPg)
                resize!(gens_thermal_bindPg_busnumber,gen_bindPg)
                gens_thermal_bindPg_name[gen_bindPg] = gen_thermal.name
                gens_thermal_bindPg_busnumber[gen_bindPg] = gen_thermal.bus.number
            end
        end
    end

    # Parse the PTDF matrix
    if gens_thermal_bindPg_busnumber == Any[]
        PTDF_bindingPg = Array{Float64}(undef,(nl,0))
    else
        sort!(gens_thermal_bindPg_busnumber)
        PTDF_bindingPg = PTDF_matrix[:,gens_thermal_bindPg_busnumber]
    end

    return gens_thermal_bindPg_busnumber, PTDF_bindingPg
end

max_stars_repo_name: invenia/MaximumGeneratorProfitTCRDD

max_issues_repo_name: invenia/MaximumGeneratorProfitTCRDD

max_forks_repo_name: invenia/MaximumGeneratorProfitTCRDD


text:
using ComplexVisual
@ComplexVisual.import_huge
using ComplexVisualGtk
@ComplexVisualGtk.import_huge

trafo = z -> (z - im) / (z + im)

domain = CV_Math2DCanvas(-4.0 + 4.0im, 4.0 - 4.0im, 100)
codomain = CV_Math2DCanvas(-4.0 + 4.0im, 4.0 - 4.0im, 100)

action_pos = CV_TranslateByOffset(ComplexF64)

vline = cv_parallel_lines(0.0+7.0im; lines=2, segments=400)

style = cv_black → cv_linewidth(4) → cv_antialias_best

lr_painters_kwargs = Dict(
    :parallel_lines_painter_domain => style ↦ CV_LinePainter(
        action_pos, vline),
    :parallel_lines_painter_codomain => style ↦ CV_LinePainter(
        w -> trafo(action_pos(w)), vline),
    :action_pos => action_pos
)

scene = cv_scene_lr_std(trafo, domain, codomain; lr_painters_kwargs)

handler = cvg_visualize(scene); cvg_wait_for_destroy(handler.window)

cvg_close(handler); cv_destroy(scene)


text:
#-------------------------------------------------------------------------------
# Test suite for 'lovo_utils.jl' file
#-------------------------------------------------------------------------------

@testset "lovo_utils" begin

    @testset "fmin_eval" begin

        f(x) = ( x[1] + x[2] ) ^ 2.0
        g(x) = x[1] - x[2]
        h(x) = 1.0 - x[1] - x[2]
        l(x) = sin( x[1] + x[2] )
        func_list = [f, g, h, l]
        r = 4

        # Test parameters
        y = [0.0, 0.0]
        set = zeros(Bool, r)
        # Expected return
        fmin_return = 0.0
        imin_return = 1
        # Test
        fmin, imin = LOWDER.fmin_eval!(func_list, r, y, set)
        @test( fmin == fmin_return )
        @test( imin == imin_return )
        @test( set == [true, true, false, true] )

        # Test parameters
        y = [0.0, 1.0]
        set = zeros(Bool, r)
        # Expected return
        fmin_return = -1.0
        imin_return = 2
        # Test
        fmin, imin = LOWDER.fmin_eval!(func_list, r, y, set)
        @test( fmin == fmin_return )
        @test( imin == imin_return )
        @test( set == [false, true, false, false] )

        # Test parameters
        y = [1.0, 1.0]
        set = zeros(Bool, r)
        # Expected return
        fmin_return = -1.0
        imin_return = 3
        # Test
        fmin, imin = LOWDER.fmin_eval!(func_list, r, y, set)
        @test( fmin == fmin_return )
        @test( imin == imin_return )
        @test( set == [false, false, true, false] )

        # Test parameters
        y = [0.0, - 1.0]
        set = zeros(Bool, r)
        # Expected return
        fmin_return = sin(- 1.0)
        imin_return = 4
        # Test
        fmin, imin = LOWDER.fmin_eval!(func_list, r, y, set)
        @test( fmin == fmin_return )
        @test( imin == imin_return )
        @test( set == [false, false, false, true] )

    end

    @testset "fi_eval" begin

        f(x) = ( x[1] + x[2] ) ^ 2.0
        g(x) = x[1] - x[2]
        h(x) = 1.0 - x[1] - x[2]
        l(x) = sin( x[1] + x[2] )
        func_list = [f, g, h, l]

        # Test parameters
        index = 1
        y = [0.0, - 1.0]
        # Expected return
        value_return = 1.0
        # Test
        value = LOWDER.fi_eval(func_list, index, y)
        @test(value == value_return)

        # Test parameters
        index = 2
        y = [1.0, 1.0]
        # Expected return
        value_return = 0.0
        # Test
        value = LOWDER.fi_eval(func_list, index, y)
        @test(value == value_return)

        # Test parameters
        index = 3
        y = [0.0, 1.0]
        # Expected return
        value_return = 0.0
        # Test
        value = LOWDER.fi_eval(func_list, index, y)
        @test(value == value_return)

        # Test parameters
        index = 4
        y = [0.0, 0.0]
        # Expected return
        value_return = 0.0
        # Test
        value = LOWDER.fi_eval(func_list, index, y)
        @test(value == value_return)

    end

    @testset "fmin_partial_eval" begin

        f(x) = ( x[1] + x[2] ) ^ 2.0
        g(x) = x[1] - x[2]
        h(x) = 1.0 - x[1] - x[2]
        l(x) = sin( x[1] + x[2] )
        func_list = [f, g, h, l]
        r = 4
        set = zeros(Bool, r)

        # Test parameters
        y = [0.0, 0.0]

        idx = 1
        fi_y = 0.0

        # Test 01
        fmin, imin = LOWDER.fmin_partial_eval!( func_list, r, idx, fi_y, y, set )
        @test( fmin == 0.0 )
        @test( imin == 1 )
        @test( set == [true, true, false, true] )

        # Test parameters
        idx = 2
        fi_y = 0.0

        # Test 02
        fmin, imin = LOWDER.fmin_partial_eval!( func_list, r, idx, fi_y, y, set )
        @test( fmin == 0.0 )
        @test( imin == 2 )
        @test( set == [true, true, false, true] )

        # Test parameters
        idx = 3
        fi_y = 1.0

        # Test 03
        fmin, imin = LOWDER.fmin_partial_eval!( func_list, r, idx, fi_y, y, set )
        @test( fmin == 0.0 )
        @test( imin == 1 )
        @test( set == [true, true, false, true] )

        # Test parameters
        idx = 4
        fi_y = 0.0

        # Test 04
        fmin, imin = LOWDER.fmin_partial_eval!( func_list, r, idx, fi_y, y, set )
        @test( fmin == 0.0 )
        @test( imin == 4 )
        @test( set == [true, true, false, true] )

        # ---

        # Test parameters
        y = [0.0, 1.0]
        idx = 3
        fi_y = 0.0

        # Test
        fmin, imin = LOWDER.fmin_partial_eval!( func_list, r, idx, fi_y, y, set )
        @test( fmin == -1.0 )
        @test( imin == 2 )
        @test( set == [false, true, false, false] )

        # ---

        # Test parameters
        y = [1.0, 1.0]
        idx = 1
        fi_y = 4.0

        # Test
        fmin, imin = LOWDER.fmin_partial_eval!( func_list, r, idx, fi_y, y, set )
        @test( fmin == -1.0 )
        @test( imin == 3 )
        @test( set == [false, false, true, false] )

        # ---

        # Test parameters
        y = [0.0, -1.0]
        idx = 1
        fi_y = 0.0

        # Test
        fmin, imin = LOWDER.fmin_partial_eval!( func_list, r, idx, fi_y, y, set )
        @test( fmin == l(y) )
        @test( imin == 4 )
        @test( set == [false, false, false, true] )

    end

end

max_stars_repo_name: aschwertner/LOWDER

max_issues_repo_name: aschwertner/LOWDER

max_forks_repo_name: aschwertner/LOWDER


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

using Markdown
using InteractiveUtils

# ╔═╡ 9e164dc1-55f8-4f75-b050-3f566f3cf328
using LinearAlgebra, NLsolve, Plots

# ╔═╡ 21305de4-1efd-11ec-071a-fd5d4d81dd65
md"""
!!! warning "Remarque importante"

	Les questions de ce *notebook* doivent être traitées de manière séquentielle : Q1, Q2... jusqu'à Q9.

"""

# ╔═╡ 50aedf4c-904a-4ef3-a113-6f21c6fc2d33
md"""
# Programmation

Quelques points vont être abordés en début de séance :

1. Deux nouveaux *packages* : `Plots` et `NLsolve` ;
1. Fonctions et types d'arguments ;
1. La notation `.` (*broadcast) ;
1. Premier (`first`) et dernier (`last`) éléments d'un tableau.

"""

# ╔═╡ 4c2ed0bd-ea08-495c-94c5-2c7e92ff29d6
md"""
# Recherche de la racine d'une fonction

Nous avons vu lors de la deuxième séance que les éléments
```math
\begin{aligned}
y_1 & \simeq y \left ( t_1 \right ), \\
y_2 & \simeq y \left ( t_2 \right ), \\
& \ldots
\end{aligned}
```
de la solution numérique du problème de Cauchy
```math
\left \{ \begin{aligned}
\dot{y} \left ( t \right ) & = f \left [ t, y \left ( t \right ) \right ], \\
y \left ( 0 \right ) & = y_0
\end{aligned} \right .
```
sont définis implicitement, c'est à dire comme racines de fonctions.

L'objectif de cette première partie est de se familiariser avec le *package* `NLsolve.jl` que nous utiliserons afin de résoudre des équations non-linéaires.

Les cellules suivantes décrivent comment obtenir la racine de la function
```math
\left ( \begin{matrix}
x_1 \\
x_2 \end{matrix} \right ) \mapsto \left ( \begin{matrix}
\left ( x_1 + 3 \right ) \left ( x_2 ^ 3 - 7 \right ) + 18 \\
\sin \left [ x_2 \exp \left ( x_1 \right ) - 1 \right ]
\end{matrix} \right )
```
à partir de la donnée initiale
```math
\left ( x_1, x_2 \right ) = \left ( 0.1, 1.2 \right ).
```

"""

# ╔═╡ d3588870-17f8-467b-928b-1b6781218296
function example!(res, x)
    res[1] = (x[1] + 3) * (x[2] ^ 3 - 7) + 18
    res[2] = sin(x[2] * exp(x[1]) - 1)
	nothing
end

# ╔═╡ 3fc5c2e0-d05f-400c-a250-6fb7207ff250
getproperty(nlsolve(example!, [0.1; 1.2]), :zero)

# ╔═╡ 688b2980-43d3-4df1-825a-2da885beb08f
md"""
1. **Cas scalaire** -- Modifier l'exemple précédent afin de résoudre l'équation de Kepler
```math
10 - x + e \sin \left ( x \right ) = 0.
```
On définira dans un premier temps la fonction `kepler!` définie ci-dessous.

"""

# ╔═╡ bd298666-6284-4b63-a217-1a0d46f2d7af
# Q1 -- À MODIFIER
function kepler!(res, x)
	res[1] = x[1]
	nothing
end

# ╔═╡ 8de162b4-2a13-48c1-b9e9-133035d842ce
if norm(nlsolve(kepler!, [0.0]).zero - [5.08912]) ≤ 1e-4
	md"""
	!!! tip "😃 Bonne réponse"

		Votre implémentation de `kepler!` est correcte.
	"""
else
	md"""
	!!! danger "😡 Mauvaise réponse"

		Vérifier votre implémentation de `kepler!`.
	"""
end

# ╔═╡ e08458c6-78f3-4b34-b8ba-79dd83441f68
md"""
2. **Cas vectoriel** -- Modifier la fonction `system!` ci-dessous afin de résoudre le système d'équations
```math
\left \{ \begin{aligned}
x_1 + x_2 + x_3 ^ 2 & = 12, \\
x_1 ^ 2 - x_2 + x_3 & = 2, \\
2x_1 - x_2 ^ 2 + x_3 & = 1.
\end{aligned} \right .
```

"""

# ╔═╡ 74375a4a-8aea-43e3-b293-562ae8d5c114
# Q2 -- À MODIFIER
function system!(res, x)
	res[1] = x[1] + 1
	res[2] = x[2] + 2
	res[3] = x[3] + 3
	nothing
end

# ╔═╡ 2b611f9e-17c7-45d3-ba04-5563e9bb7ed3
if norm(nlsolve(system!, [0.0; 0.0; 0.0]).zero - [1.0; 2.0; 3.0]) ≤ 1e-4
	md"""
	!!! tip "😃 Bonne réponse"

		Votre implémentation de `system!` est correcte.
	"""
else
	md"""
	!!! danger "😡 Mauvaise réponse"

		Vérifier votre implémentation de `system!`.
	"""
end

# ╔═╡ 586ecaf0-6a36-468f-998c-d22cbb869990
md"""
# Modèle et solution exacte

On se concentre pour l'instant sur le modèle linéaire homogène pour lequel le second membre de l'EDO s'écrit
```math
f \colon \left ( t, y \right ) \mapsto \lambda y.
```

L'équation différentielle à résoudre s'écrit alors,
```math
\left \{ \begin{aligned}
\dot{y} \left ( t \right ) & = \lambda y \left ( t \right ), \\
y \left ( 0 \right ) & = y_0
\end{aligned} \right .
```
et la solution exacte est donnée sous la forme :
```math
y \colon t \mapsto \exp \left ( \lambda t \right ) y_0.
```

3. Implémenter la fonction ``f``, appelée ci-dessous `linear`, dans le cas ``\lambda = -1``.

"""

# ╔═╡ b147630e-e17e-48ca-8733-a0588f6e6d3b
# Q3 -- À MODIFIER
linear(t, y) = zero(y)

# ╔═╡ 293dea21-2128-41d3-b11c-47225d27d168
if norm(linear(nothing, [π; 2 // 3]) + [π; 2 // 3]) ≤ 1e-4
	md"""
	!!! tip "😃 Bonne réponse"

		Votre implémentation de `linear` est correcte.
	"""
else
	md"""
	!!! danger "😡 Mauvaise réponse"

		Vérifier votre implémentation de `linear`.
	"""
end

# ╔═╡ 344724c5-f849-4234-aa21-2c6e48a042c0
md"""
4. Implémenter la fonction `solution` qui correspond à la solution analytique dans le cas ``\lambda = -1`` et ``y_0 = 1``.

"""

# ╔═╡ 4dafb136-cadb-4689-8511-01b72b308515
# Q4 -- À MODIFIER
solution(t, y = ones(1)) = zero(y)

# ╔═╡ 957c5d5f-df77-463e-8cc8-3affec13a636
if norm(solution(1.0) - [0.36788]) ≤ 1e-4
	md"""
	!!! tip "😃 Bonne réponse"

		Votre implémentation de `solution` est correcte.
	"""
else
	md"""
	!!! danger "😡 Mauvaise réponse"

		Vérifier votre implémentation de `solution`.
	"""
end

# ╔═╡ f0559c7f-83ed-4797-8fe1-d87ed27419fa
md"""
# Schéma numérique

On rappelle que lors du cours précédent, tois schémas numériques ont été présentés, à savoir :
```math
y_{n + 1} - y_n - \tau f \left ( t_n, y_n \right ) = 0 \quad \text{(Euler explicite)},
```
```math
y_{n + 1} - y_n - \tau f \left ( t_{n + 1}, y_{n + 1} \right ) = 0 \quad \text{(Euler implicite)},
```
et
```math
y_{n + 1} - y_n - \tau f \left ( \frac{t_n + t_{n + 1}}{2}, \frac{y_n + y_{n + 1}}{2} \right ) = 0 \quad \text{(point milieu)}.
```

5. En vous inspirant de l'implémentation `explicit!` du schéma explicite d'Euler présentée ci-dessous, implémenter les fonctions `implicit!` (a) et `midpoint!` (b) dont la racine est ``y_{n + 1}``. On préservera le nombre et l'ordre des paramètres, au nombre de 6, à savoir

* `res` -- la valeur de la fonction implicite ;
* `x` -- la solution mise à jour (``y _ {n + 1}``) ;
* `y` -- la solution précédente (``y _ n``) ;
* `τ` -- le pas de temps (``\tau``) ;
* `f` -- le modèle (``f``) ;
* `t` -- l'instant précédent, (``t _ n``).

Pour le schéma d'Euler explicite, la solution mise à jour ``y_{n + 1}`` est donc définie comme la racine de la fonction implicite suivante
```math
F \left ( x, y, \tau, f, t \right ) = x - y - \tau f \left ( t, y \right ),
```
implémentée à l'aide de la fonction `explicit!` ci-dessous.

"""

# ╔═╡ 293407bc-2958-407f-b82b-d28f94023b60
md"""
!!! note "De l'usage de `!` en Julia"

	Par convention, `!` (*bang* en anglais) est ajouté à la fin du nom d'une fonction lorsque celle-ci modifie son premier argument (ici, `res`).

"""

# ╔═╡ 02ef58f1-235a-4108-917d-5c2e7e0527a1
function explicit!(res, x, y, τ, f, t)
	res .= x - y - τ * f(t, y)
end

# ╔═╡ c00f201c-b2b9-4226-ae7f-82269a399199
md"""
Modifier la fonction `implicit!` ci-dessous pour qu'elle corresponde au schéma d'Euler implicite
```math
F \left ( x, y, \tau, f, t \right ) = x - y - \tau f \left ( t + \tau, x \right ).
```

"""

# ╔═╡ fb414e6a-52ee-419c-b2dc-c320c27f17e2
# Q5a -- À MODIFIER
function implicit!(res, x, y, τ, f, t)
	res .= x - y - τ * f(t, y)
end

# ╔═╡ c0a78db4-794e-48f8-a34d-d7fcbddb279b
if norm(implicit!(zeros(1), ones(1), ones(1), √2, (t, y) -> t .+ y, π) - [-7.8571]) ≤ 1e-4
	md"""
	!!! tip "😃 Bonne réponse"

		Votre implémentation de `implicit!` est correcte.
	"""
else
	md"""
	!!! danger "😡 Mauvaise réponse"

		Vérifier votre implémentation de `implicit!`.
	"""
end

# ╔═╡ 8825a1ac-5c1c-47fb-b16d-aade27463ad3
md"""
De même, modifier la fonction `midpoint!` ci-dessous pour lui faire correspondre le schéma du point milieu, qui s'écrira
```math
F \left ( x, y, \tau, f, t \right ) = x - y - \tau f \left ( t + \frac{\tau}{2}, \frac{x + y}{2} \right ).
```

"""

# ╔═╡ 1e4def72-64a4-4b2e-bf0f-86a4ee57bc10
# Q5b -- À MODIFIER
function midpoint!(res, x, y, τ, f, t)
	res .= x - y - τ * f(t, y)
end

# ╔═╡ a37aa68d-f4ff-4fb2-b8d2-ff80bd67b6a1
if norm(midpoint!(zeros(1), ones(1), ones(1), √2, (t, y) -> t .+ y, π) - [-6.8571]) ≤ 1e-4
	md"""
	!!! tip "😃 Bonne réponse"

		Votre implémentation de `midpoint!` est correcte.
	"""
else
	md"""
	!!! danger "😡 Mauvaise réponse"

		Vérifier votre implémentation de `midpoint!`.
	"""
end

# ╔═╡ 690dbae8-a720-4d51-87a2-7834d84ee60b
md"""
# Intégration temporelle

Il reste à présent à assembler à implémenter la bouche d'intégration temporelle. Étant donnés

* Un modèle `f` ;
* Un pas de temps `τ` ;
* Et un instant `s`

la fonction `cauchy` implémentée ci-dessous retourne deux vecteurs, le premier contenant les instants
```math
t_0 \quad t_1 \quad \cdots \quad t_N = s
```
et le second la solution numérique, à savoir
```math
y_0 \quad y_1 \quad \cdots \quad y_N.
```

"""

# ╔═╡ 14baffbc-2cf0-4b6c-8b35-bfaf0605575c
function cauchy(scheme!, f, τ, s, y₀, t₀ = zero(τ))
	t, y = t₀, y₀
    T, Y = [t], [y]

	while t < (1 - √eps(t)) * s
		y = getproperty(
			nlsolve(y) do res, x
				scheme!(res, x, y, τ, f, t)
			end,
			:zero
		)
        t += τ

        push!(Y, y)
        push!(T, t)
	end

	T, Y
end

# ╔═╡ 99b7cb68-508a-40ad-9007-4fbe9eb676ce
md"""
La solution numérique peut être obtenue et visualisée comme suit.

"""

# ╔═╡ 7e3b1dd7-dfc7-48b8-9c0d-9d71d8d3ea62
begin
	local T, Y = cauchy(explicit!, linear, 0.5, 10.0, ones(1))
	local fig = plot()
	scatter!(fig, T, first.(Y), label = "num")
	plot!(fig, t -> first.(solution.(t)), label = "exact")
end

# ╔═╡ a89a5fee-a28d-43df-be08-a146c476a5db
md"""
6. Utiliser les fonctions `linear` et `solution` définie précédemment dans l'implémentation de la fonction `error` ci-dessous, qui calcule l'erreur
```math
y_N - y \left ( t_N \right )
```
en fonction du schéma (`scheme!`) et du pas en temps (`τ`).

"""

# ╔═╡ c1c0ea70-fc6b-4928-adff-e58edd22d7e0
# Q6 -- À MODIFIER
function error(scheme!, τ, s)
	T, num = cauchy(scheme!, linear, τ, s, ones(1))
	exact = solution.(T)
	norm(last(num))
end

# ╔═╡ f5c664fc-9877-4800-b261-d9233d4c006a
if norm(error(explicit!, 0.2, 1.0) - 0.0401994) ≤ 1e-4
	md"""
	!!! tip "😃 Bonne réponse"

		Votre implémentation de `error` est correcte.
	"""
else
	md"""
	!!! danger "😡 Mauvaise réponse"

		Vérifier votre implémentation de `error`.
	"""
end

# ╔═╡ b796ff78-0741-42b3-8285-b01a042feabc
md"""
7. Calculer (en utilisant la fonction `error`) et reporter les erreurs à l'instant `s = 1.0` dans le tableau ci-dessous. Commenter.

|             | `explicit!` | `implicit!` | `midpoint!` |
|:-----------:|:-----------:|:-----------:|:-----------:|
| `τ = 0.125` |             |             |             |
| `τ = 0.25`  |             |             |             |
| `τ = 0.5`   |             |             |             |
| `τ = 1.0`   |             |             |             |

8. On se place maintenant sur un horizon temporel plus long (`s = 10.0`). Augmenter la taille du pas de temps et commenter.

"""

# ╔═╡ a8242689-1552-4261-b1b8-767fa80b74ea
md"""

Tout l'intérêt de l'utilisation du package `NLsolve.jl` est que notre implémentation fonctionne pour les problèmes scalaires **non-linéaires**, ainsi que pour les cas **vectoriels**.

# Au delà du cas linéaire

9. Utiliser ou imaginer un modèle scalaire non-linéaire en modifier la fonction `nonlinear` ci-dessous, et visualiser votre solution numérique pour chacun des trois schémas sur le même graphique. Vous pourrez par exemple utiliser la question 3 de l'exercice vu en TD :
```math
f \colon \left ( t, y \right ) \mapsto 2t - y ^ 2.
```

!!! note "De l'usage du point"

	En Julia, le point (`.`) permet d'appliquer une fonction à chaque élément d'un tableau. Par exemple, la commande suivante élève chaque élément du tableau `y` au carré :
	```julia
	y .^ 2
	```

	Dans le doute, on peut aussi utiliser la *macro* `@.` comme suit :
	```julia
	@. y ^ 2
	```
    En un sens, elle "saupoudre" l'expression qui la suit de points.

"""

# ╔═╡ 1c422e7a-3e59-4b4a-af58-cfb1e5818c53
# Q9 -- À MODIFIER
nonlinear(t, y) = @. y

# ╔═╡ 778c181e-7253-4666-9075-14aa9f0315fa
if norm(nonlinear(π, [√2]) - [4.28319]) ≤ 1e-4
	md"""
	!!! tip "😃 Bonne réponse"

		Votre implémentation de `nonlinear` est correcte.
	"""
else
	md"""
	!!! danger "😡 Mauvaise réponse"

		Vérifier votre implémentation de `nonlinear`.
	"""
end

# ╔═╡ d2f5d13a-cd95-42e4-b6b8-d60e4057f93a
begin
	local T, Y = cauchy(explicit!, nonlinear, 0.1, 1.0, ones(1))
	local fig = plot()
	scatter!(fig, T, first.(Y), label = "num")
end

# ╔═╡ 00000000-0000-0000-0000-000000000001
PLUTO_PROJECT_TOML_CONTENTS = """
[deps]
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
NLsolve = "2774e3e8-f4cf-5e23-947b-6d7e65073b56"
Plots = "91a5bcdd-55d7-5caf-9e0b-520d859cae80"

[compat]
NLsolve = "~4.5.1"
Plots = "~1.22.2"
"""

# ╔═╡ 00000000-0000-0000-0000-000000000002
PLUTO_MANIFEST_TOML_CONTENTS = """
# This file is machine-generated - editing it directly is not advised

julia_version = "1.7.0-beta4"
manifest_format = "2.0"

[[deps.Adapt]]
deps = ["LinearAlgebra"]
git-tree-sha1 = "84918055d15b3114ede17ac6a7182f68870c16f7"
uuid = "79e6a3ab-5dfb-504d-930d-738a2a938a0e"
version = "3.3.1"

[[deps.ArgTools]]
uuid = "0dad84c5-d112-42e6-8d28-ef12dabb789f"

[[deps.ArrayInterface]]
deps = ["Compat", "IfElse", "LinearAlgebra", "Requires", "SparseArrays", "Static"]
git-tree-sha1 = "b8d49c34c3da35f220e7295659cd0bab8e739fed"
uuid = "4fba245c-0d91-5ea0-9b3e-6abc04ee57a9"
version = "3.1.33"

[[deps.Artifacts]]
uuid = "56f22d72-fd6d-98f1-02f0-08ddc0907c33"

[[deps.Base64]]
uuid = "2a0f44e3-6c83-55bd-87e4-b1978d98bd5f"

[[deps.Bzip2_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "19a35467a82e236ff51bc17a3a44b69ef35185a2"
uuid = "6e34b625-4abd-537c-b88f-471c36dfa7a0"
version = "1.0.8+0"

[[deps.Cairo_jll]]
deps = ["Artifacts", "Bzip2_jll", "Fontconfig_jll", "FreeType2_jll", "Glib_jll", "JLLWrappers", "LZO_jll", "Libdl", "Pixman_jll", "Pkg", "Xorg_libXext_jll", "Xorg_libXrender_jll", "Zlib_jll", "libpng_jll"]
git-tree-sha1 = "f2202b55d816427cd385a9a4f3ffb226bee80f99"
uuid = "83423d85-b0ee-5818-9007-b63ccbeb887a"
version = "1.16.1+0"

[[deps.ChainRulesCore]]
deps = ["Compat", "LinearAlgebra", "SparseArrays"]
git-tree-sha1 = "bd4afa1fdeec0c8b89dad3c6e92bc6e3b0fec9ce"
uuid = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4"
version = "1.6.0"

[[deps.ColorSchemes]]
deps = ["ColorTypes", "Colors", "FixedPointNumbers", "Random"]
git-tree-sha1 = "a851fec56cb73cfdf43762999ec72eff5b86882a"
uuid = "35d6a980-a343-548e-a6ea-1d62b119f2f4"
version = "3.15.0"

[[deps.ColorTypes]]
deps = ["FixedPointNumbers", "Random"]
git-tree-sha1 = "024fe24d83e4a5bf5fc80501a314ce0d1aa35597"
uuid = "3da002f7-5984-5a60-b8a6-cbb66c0b333f"
version = "0.11.0"

[[deps.Colors]]
deps = ["ColorTypes", "FixedPointNumbers", "Reexport"]
git-tree-sha1 = "417b0ed7b8b838aa6ca0a87aadf1bb9eb111ce40"
uuid = "5ae59095-9a9b-59fe-a467-6f913c188581"
version = "0.12.8"

[[deps.CommonSubexpressions]]
deps = ["MacroTools", "Test"]
git-tree-sha1 = "7b8a93dba8af7e3b42fecabf646260105ac373f7"
uuid = "bbf7d656-a473-5ed7-a52c-81e309532950"
version = "0.3.0"

[[deps.Compat]]
deps = ["Base64", "Dates", "DelimitedFiles", "Distributed", "InteractiveUtils", "LibGit2", "Libdl", "LinearAlgebra", "Markdown", "Mmap", "Pkg", "Printf", "REPL", "Random", "SHA", "Serialization", "SharedArrays", "Sockets", "SparseArrays", "Statistics", "Test", "UUIDs", "Unicode"]
git-tree-sha1 = "31d0151f5716b655421d9d75b7fa74cc4e744df2"
uuid = "34da2185-b29b-5c13-b0c7-acf172513d20"
version = "3.39.0"

[[deps.CompilerSupportLibraries_jll]]
deps = ["Artifacts", "Libdl"]
uuid = "e66e0078-7015-5450-92f7-15fbd957f2ae"

[[deps.Contour]]
deps = ["StaticArrays"]
git-tree-sha1 = "9f02045d934dc030edad45944ea80dbd1f0ebea7"
uuid = "d38c429a-6771-53c6-b99e-75d170b6e991"
version = "0.5.7"

[[deps.DataAPI]]
git-tree-sha1 = "cc70b17275652eb47bc9e5f81635981f13cea5c8"
uuid = "9a962f9c-6df0-11e9-0e5d-c546b8b5ee8a"
version = "1.9.0"

[[deps.DataStructures]]
deps = ["Compat", "InteractiveUtils", "OrderedCollections"]
git-tree-sha1 = "7d9d316f04214f7efdbb6398d545446e246eff02"
uuid = "864edb3b-99cc-5e75-8d2d-829cb0a9cfe8"
version = "0.18.10"

[[deps.DataValueInterfaces]]
git-tree-sha1 = "bfc1187b79289637fa0ef6d4436ebdfe6905cbd6"
uuid = "e2d170a0-9d28-54be-80f0-106bbe20a464"
version = "1.0.0"

[[deps.Dates]]
deps = ["Printf"]
uuid = "ade2ca70-3891-5945-98fb-dc099432e06a"

[[deps.DelimitedFiles]]
deps = ["Mmap"]
uuid = "8bb1440f-4735-579b-a4ab-409b98df4dab"

[[deps.DiffResults]]
deps = ["StaticArrays"]
git-tree-sha1 = "c18e98cba888c6c25d1c3b048e4b3380ca956805"
uuid = "163ba53b-c6d8-5494-b064-1a9d43ac40c5"
version = "1.0.3"

[[deps.DiffRules]]
deps = ["NaNMath", "Random", "SpecialFunctions"]
git-tree-sha1 = "7220bc21c33e990c14f4a9a319b1d242ebc5b269"
uuid = "b552c78f-8df3-52c6-915a-8e097449b14b"
version = "1.3.1"

[[deps.Distances]]
deps = ["LinearAlgebra", "Statistics", "StatsAPI"]
git-tree-sha1 = "9f46deb4d4ee4494ffb5a40a27a2aced67bdd838"
uuid = "b4f34e82-e78d-54a5-968a-f98e89d6e8f7"
version = "0.10.4"

[[deps.Distributed]]
deps = ["Random", "Serialization", "Sockets"]
uuid = "8ba89e20-285c-5b6f-9357-94700520ee1b"

[[deps.DocStringExtensions]]
deps = ["LibGit2"]
git-tree-sha1 = "a32185f5428d3986f47c2ab78b1f216d5e6cc96f"
uuid = "ffbed154-4ef7-542d-bbb7-c09d3a79fcae"
version = "0.8.5"

[[deps.Downloads]]
deps = ["ArgTools", "LibCURL", "NetworkOptions"]
uuid = "f43a241f-c20a-4ad4-852c-f6b1247861c6"

[[deps.EarCut_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "3f3a2501fa7236e9b911e0f7a588c657e822bb6d"
uuid = "5ae413db-bbd1-5e63-b57d-d24a61df00f5"
version = "2.2.3+0"

[[deps.Expat_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "b3bfd02e98aedfa5cf885665493c5598c350cd2f"
uuid = "2e619515-83b5-522b-bb60-26c02a35a201"
version = "2.2.10+0"

[[deps.FFMPEG]]
deps = ["FFMPEG_jll"]
git-tree-sha1 = "b57e3acbe22f8484b4b5ff66a7499717fe1a9cc8"
uuid = "c87230d0-a227-11e9-1b43-d7ebe4e7570a"
version = "0.4.1"

[[deps.FFMPEG_jll]]
deps = ["Artifacts", "Bzip2_jll", "FreeType2_jll", "FriBidi_jll", "JLLWrappers", "LAME_jll", "Libdl", "Ogg_jll", "OpenSSL_jll", "Opus_jll", "Pkg", "Zlib_jll", "libass_jll", "libfdk_aac_jll", "libvorbis_jll", "x264_jll", "x265_jll"]
git-tree-sha1 = "d8a578692e3077ac998b50c0217dfd67f21d1e5f"
uuid = "b22a6f82-2f65-5046-a5b2-351ab43fb4e5"
version = "4.4.0+0"

[[deps.FiniteDiff]]
deps = ["ArrayInterface", "LinearAlgebra", "Requires", "SparseArrays", "StaticArrays"]
git-tree-sha1 = "8b3c09b56acaf3c0e581c66638b85c8650ee9dca"
uuid = "6a86dc24-6348-571c-b903-95158fe2bd41"
version = "2.8.1"

[[deps.FixedPointNumbers]]
deps = ["Statistics"]
git-tree-sha1 = "335bfdceacc84c5cdf16aadc768aa5ddfc5383cc"
uuid = "53c48c17-4a7d-5ca2-90c5-79b7896eea93"
version = "0.8.4"

[[deps.Fontconfig_jll]]
deps = ["Artifacts", "Bzip2_jll", "Expat_jll", "FreeType2_jll", "JLLWrappers", "Libdl", "Libuuid_jll", "Pkg", "Zlib_jll"]
git-tree-sha1 = "21efd19106a55620a188615da6d3d06cd7f6ee03"
uuid = "a3f928ae-7b40-5064-980b-68af3947d34b"
version = "2.13.93+0"

[[deps.Formatting]]
deps = ["Printf"]
git-tree-sha1 = "8339d61043228fdd3eb658d86c926cb282ae72a8"
uuid = "59287772-0a20-5a39-b81b-1366585eb4c0"
version = "0.4.2"

[[deps.ForwardDiff]]
deps = ["CommonSubexpressions", "DiffResults", "DiffRules", "LinearAlgebra", "NaNMath", "Printf", "Random", "SpecialFunctions", "StaticArrays"]
git-tree-sha1 = "b5e930ac60b613ef3406da6d4f42c35d8dc51419"
uuid = "f6369f11-7733-5829-9624-2563aa707210"
version = "0.10.19"

[[deps.FreeType2_jll]]
deps = ["Artifacts", "Bzip2_jll", "JLLWrappers", "Libdl", "Pkg", "Zlib_jll"]
git-tree-sha1 = "87eb71354d8ec1a96d4a7636bd57a7347dde3ef9"
uuid = "d7e528f0-a631-5988-bf34-fe36492bcfd7"
version = "2.10.4+0"

[[deps.FriBidi_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "aa31987c2ba8704e23c6c8ba8a4f769d5d7e4f91"
uuid = "559328eb-81f9-559d-9380-de523a88c83c"
version = "1.0.10+0"

[[deps.GLFW_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Libglvnd_jll", "Pkg", "Xorg_libXcursor_jll", "Xorg_libXi_jll", "Xorg_libXinerama_jll", "Xorg_libXrandr_jll"]
git-tree-sha1 = "dba1e8614e98949abfa60480b13653813d8f0157"
uuid = "0656b61e-2033-5cc2-a64a-77c0f6c09b89"
version = "3.3.5+0"

[[deps.GR]]
deps = ["Base64", "DelimitedFiles", "GR_jll", "HTTP", "JSON", "Libdl", "LinearAlgebra", "Pkg", "Printf", "Random", "Serialization", "Sockets", "Test", "UUIDs"]
git-tree-sha1 = "c2178cfbc0a5a552e16d097fae508f2024de61a3"
uuid = "28b8d3ca-fb5f-59d9-8090-bfdbd6d07a71"
version = "0.59.0"

[[deps.GR_jll]]
deps = ["Artifacts", "Bzip2_jll", "Cairo_jll", "FFMPEG_jll", "Fontconfig_jll", "GLFW_jll", "JLLWrappers", "JpegTurbo_jll", "Libdl", "Libtiff_jll", "Pixman_jll", "Pkg", "Qt5Base_jll", "Zlib_jll", "libpng_jll"]
git-tree-sha1 = "ef49a187604f865f4708c90e3f431890724e9012"
uuid = "d2c73de3-f751-5644-a686-071e5b155ba9"
version = "0.59.0+0"

[[deps.GeometryBasics]]
deps = ["EarCut_jll", "IterTools", "LinearAlgebra", "StaticArrays", "StructArrays", "Tables"]
git-tree-sha1 = "58bcdf5ebc057b085e58d95c138725628dd7453c"
uuid = "5c1252a2-5f33-56bf-86c9-59e7332b4326"
version = "0.4.1"

[[deps.Gettext_jll]]
deps = ["Artifacts", "CompilerSupportLibraries_jll", "JLLWrappers", "Libdl", "Libiconv_jll", "Pkg", "XML2_jll"]
git-tree-sha1 = "9b02998aba7bf074d14de89f9d37ca24a1a0b046"
uuid = "78b55507-aeef-58d4-861c-77aaff3498b1"
version = "0.21.0+0"

[[deps.Glib_jll]]
deps = ["Artifacts", "Gettext_jll", "JLLWrappers", "Libdl", "Libffi_jll", "Libiconv_jll", "Libmount_jll", "PCRE_jll", "Pkg", "Zlib_jll"]
git-tree-sha1 = "7bf67e9a481712b3dbe9cb3dac852dc4b1162e02"
uuid = "7746bdde-850d-59dc-9ae8-88ece973131d"
version = "2.68.3+0"

[[deps.Graphite2_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "344bf40dcab1073aca04aa0df4fb092f920e4011"
uuid = "3b182d85-2403-5c21-9c21-1e1f0cc25472"
version = "1.3.14+0"

[[deps.Grisu]]
git-tree-sha1 = "53bb909d1151e57e2484c3d1b53e19552b887fb2"
uuid = "42e2da0e-8278-4e71-bc24-59509adca0fe"
version = "1.0.2"

[[deps.HTTP]]
deps = ["Base64", "Dates", "IniFile", "Logging", "MbedTLS", "NetworkOptions", "Sockets", "URIs"]
git-tree-sha1 = "24675428ca27678f003414a98c9e473e45fe6a21"
uuid = "cd3eb016-35fb-5094-929b-558a96fad6f3"
version = "0.9.15"

[[deps.HarfBuzz_jll]]
deps = ["Artifacts", "Cairo_jll", "Fontconfig_jll", "FreeType2_jll", "Glib_jll", "Graphite2_jll", "JLLWrappers", "Libdl", "Libffi_jll", "Pkg"]
git-tree-sha1 = "8a954fed8ac097d5be04921d595f741115c1b2ad"
uuid = "2e76f6c2-a576-52d4-95c1-20adfe4de566"
version = "2.8.1+0"

[[deps.IfElse]]
git-tree-sha1 = "28e837ff3e7a6c3cdb252ce49fb412c8eb3caeef"
uuid = "615f187c-cbe4-4ef1-ba3b-2fcf58d6d173"
version = "0.1.0"

[[deps.IniFile]]
deps = ["Test"]
git-tree-sha1 = "098e4d2c533924c921f9f9847274f2ad89e018b8"
uuid = "83e8ac13-25f8-5344-8a64-a9f2b223428f"
version = "0.5.0"

[[deps.InteractiveUtils]]
deps = ["Markdown"]
uuid = "b77e0a4c-d291-57a0-90e8-8db25a27a240"

[[deps.IrrationalConstants]]
git-tree-sha1 = "f76424439413893a832026ca355fe273e93bce94"
uuid = "92d709cd-6900-40b7-9082-c6be49f344b6"
version = "0.1.0"

[[deps.IterTools]]
git-tree-sha1 = "05110a2ab1fc5f932622ffea2a003221f4782c18"
uuid = "c8e1da08-722c-5040-9ed9-7db0dc04731e"
version = "1.3.0"

[[deps.IteratorInterfaceExtensions]]
git-tree-sha1 = "a3f24677c21f5bbe9d2a714f95dcd58337fb2856"
uuid = "82899510-4779-5014-852e-03e436cf321d"
version = "1.0.0"

[[deps.JLLWrappers]]
deps = ["Preferences"]
git-tree-sha1 = "642a199af8b68253517b80bd3bfd17eb4e84df6e"
uuid = "692b3bcd-3c85-4b1f-b108-f13ce0eb3210"
version = "1.3.0"

[[deps.JSON]]
deps = ["Dates", "Mmap", "Parsers", "Unicode"]
git-tree-sha1 = "8076680b162ada2a031f707ac7b4953e30667a37"
uuid = "682c06a0-de6a-54ab-a142-c8b1cf79cde6"
version = "0.21.2"

[[deps.JpegTurbo_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "d735490ac75c5cb9f1b00d8b5509c11984dc6943"
uuid = "aacddb02-875f-59d6-b918-886e6ef4fbf8"
version = "2.1.0+0"

[[deps.LAME_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "f6250b16881adf048549549fba48b1161acdac8c"
uuid = "c1c5ebd0-6772-5130-a774-d5fcae4a789d"
version = "3.100.1+0"

[[deps.LZO_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "e5b909bcf985c5e2605737d2ce278ed791b89be6"
uuid = "dd4b983a-f0e5-5f8d-a1b7-129d4a5fb1ac"
version = "2.10.1+0"

[[deps.LaTeXStrings]]
git-tree-sha1 = "c7f1c695e06c01b95a67f0cd1d34994f3e7db104"
uuid = "b964fa9f-0449-5b57-a5c2-d3ea65f4040f"
version = "1.2.1"

[[deps.Latexify]]
deps = ["Formatting", "InteractiveUtils", "LaTeXStrings", "MacroTools", "Markdown", "Printf", "Requires"]
git-tree-sha1 = "a4b12a1bd2ebade87891ab7e36fdbce582301a92"
uuid = "23fbe1c1-3f47-55db-b15f-69d7ec21a316"
version = "0.15.6"

[[deps.LibCURL]]
deps = ["LibCURL_jll", "MozillaCACerts_jll"]
uuid = "b27032c2-a3e7-50c8-80cd-2d36dbcbfd21"

[[deps.LibCURL_jll]]
deps = ["Artifacts", "LibSSH2_jll", "Libdl", "MbedTLS_jll", "Zlib_jll", "nghttp2_jll"]
uuid = "deac9b47-8bc7-5906-a0fe-35ac56dc84c0"

[[deps.LibGit2]]
deps = ["Base64", "NetworkOptions", "Printf", "SHA"]
uuid = "76f85450-5226-5b5a-8eaa-529ad045b433"

[[deps.LibSSH2_jll]]
deps = ["Artifacts", "Libdl", "MbedTLS_jll"]
uuid = "29816b5a-b9ab-546f-933c-edad1886dfa8"

[[deps.Libdl]]
uuid = "8f399da3-3557-5675-b5ff-fb832c97cbdb"

[[deps.Libffi_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "761a393aeccd6aa92ec3515e428c26bf99575b3b"
uuid = "e9f186c6-92d2-5b65-8a66-fee21dc1b490"
version = "3.2.2+0"

[[deps.Libgcrypt_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Libgpg_error_jll", "Pkg"]
git-tree-sha1 = "64613c82a59c120435c067c2b809fc61cf5166ae"
uuid = "d4300ac3-e22c-5743-9152-c294e39db1e4"
version = "1.8.7+0"

[[deps.Libglvnd_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_libX11_jll", "Xorg_libXext_jll"]
git-tree-sha1 = "7739f837d6447403596a75d19ed01fd08d6f56bf"
uuid = "7e76a0d4-f3c7-5321-8279-8d96eeed0f29"
version = "1.3.0+3"

[[deps.Libgpg_error_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "c333716e46366857753e273ce6a69ee0945a6db9"
uuid = "7add5ba3-2f88-524e-9cd5-f83b8a55f7b8"
version = "1.42.0+0"

[[deps.Libiconv_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "42b62845d70a619f063a7da093d995ec8e15e778"
uuid = "94ce4f54-9a6c-5748-9c1c-f9c7231a4531"
version = "1.16.1+1"

[[deps.Libmount_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "9c30530bf0effd46e15e0fdcf2b8636e78cbbd73"
uuid = "4b2f31a3-9ecc-558c-b454-b3730dcb73e9"
version = "2.35.0+0"

[[deps.Libtiff_jll]]
deps = ["Artifacts", "JLLWrappers", "JpegTurbo_jll", "Libdl", "Pkg", "Zlib_jll", "Zstd_jll"]
git-tree-sha1 = "340e257aada13f95f98ee352d316c3bed37c8ab9"
uuid = "89763e89-9b03-5906-acba-b20f662cd828"
version = "4.3.0+0"

[[deps.Libuuid_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "7f3efec06033682db852f8b3bc3c1d2b0a0ab066"
uuid = "38a345b3-de98-5d2b-a5d3-14cd9215e700"
version = "2.36.0+0"

[[deps.LineSearches]]
deps = ["LinearAlgebra", "NLSolversBase", "NaNMath", "Parameters", "Printf"]
git-tree-sha1 = "f27132e551e959b3667d8c93eae90973225032dd"
uuid = "d3d80556-e9d4-5f37-9878-2ab0fcc64255"
version = "7.1.1"

[[deps.LinearAlgebra]]
deps = ["Libdl", "libblastrampoline_jll"]
uuid = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"

[[deps.LogExpFunctions]]
deps = ["ChainRulesCore", "DocStringExtensions", "IrrationalConstants", "LinearAlgebra"]
git-tree-sha1 = "34dc30f868e368f8a17b728a1238f3fcda43931a"
uuid = "2ab3a3ac-af41-5b50-aa03-7779005ae688"
version = "0.3.3"

[[deps.Logging]]
uuid = "56ddb016-857b-54e1-b83d-db4d58db5568"

[[deps.MacroTools]]
deps = ["Markdown", "Random"]
git-tree-sha1 = "5a5bc6bf062f0f95e62d0fe0a2d99699fed82dd9"
uuid = "1914dd2f-81c6-5fcd-8719-6d5c9610ff09"
version = "0.5.8"

[[deps.Markdown]]
deps = ["Base64"]
uuid = "d6f4376e-aef5-505a-96c1-9c027394607a"

[[deps.MbedTLS]]
deps = ["Dates", "MbedTLS_jll", "Random", "Sockets"]
git-tree-sha1 = "1c38e51c3d08ef2278062ebceade0e46cefc96fe"
uuid = "739be429-bea8-5141-9913-cc70e7f3736d"
version = "1.0.3"

[[deps.MbedTLS_jll]]
deps = ["Artifacts", "Libdl"]
uuid = "c8ffd9c3-330d-5841-b78e-0817d7145fa1"

[[deps.Measures]]
git-tree-sha1 = "e498ddeee6f9fdb4551ce855a46f54dbd900245f"
uuid = "442fdcdd-2543-5da2-b0f3-8c86c306513e"
version = "0.3.1"

[[deps.Missings]]
deps = ["DataAPI"]
git-tree-sha1 = "bf210ce90b6c9eed32d25dbcae1ebc565df2687f"
uuid = "e1d29d7a-bbdc-5cf2-9ac0-f12de2c33e28"
version = "1.0.2"

[[deps.Mmap]]
uuid = "a63ad114-7e13-5084-954f-fe012c677804"

[[deps.MozillaCACerts_jll]]
uuid = "14a3606d-f60d-562e-9121-12d972cd8159"

[[deps.NLSolversBase]]
deps = ["DiffResults", "Distributed", "FiniteDiff", "ForwardDiff"]
git-tree-sha1 = "144bab5b1443545bc4e791536c9f1eacb4eed06a"
uuid = "d41bc354-129a-5804-8e4c-c37616107c6c"
version = "7.8.1"

[[deps.NLsolve]]
deps = ["Distances", "LineSearches", "LinearAlgebra", "NLSolversBase", "Printf", "Reexport"]
git-tree-sha1 = "019f12e9a1a7880459d0173c182e6a99365d7ac1"
uuid = "2774e3e8-f4cf-5e23-947b-6d7e65073b56"
version = "4.5.1"

[[deps.NaNMath]]
git-tree-sha1 = "bfe47e760d60b82b66b61d2d44128b62e3a369fb"
uuid = "77ba4419-2d1f-58cd-9bb1-8ffee604a2e3"
version = "0.3.5"

[[deps.NetworkOptions]]
uuid = "ca575930-c2e3-43a9-ace4-1e988b2c1908"

[[deps.Ogg_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "7937eda4681660b4d6aeeecc2f7e1c81c8ee4e2f"
uuid = "e7412a2a-1a6e-54c0-be00-318e2571c051"
version = "1.3.5+0"

[[deps.OpenBLAS_jll]]
deps = ["Artifacts", "CompilerSupportLibraries_jll", "Libdl"]
uuid = "4536629a-c528-5b80-bd46-f80d51c5b363"

[[deps.OpenLibm_jll]]
deps = ["Artifacts", "Libdl"]
uuid = "05823500-19ac-5b8b-9628-191a04bc5112"

[[deps.OpenSSL_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "15003dcb7d8db3c6c857fda14891a539a8f2705a"
uuid = "458c3c95-2e84-50aa-8efc-19380b2a3a95"
version = "1.1.10+0"

[[deps.OpenSpecFun_jll]]
deps = ["Artifacts", "CompilerSupportLibraries_jll", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "13652491f6856acfd2db29360e1bbcd4565d04f1"
uuid = "efe28fd5-8261-553b-a9e1-b2916fc3738e"
version = "0.5.5+0"

[[deps.Opus_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "51a08fb14ec28da2ec7a927c4337e4332c2a4720"
uuid = "91d4177d-7536-5919-b921-800302f37372"
version = "1.3.2+0"

[[deps.OrderedCollections]]
git-tree-sha1 = "85f8e6578bf1f9ee0d11e7bb1b1456435479d47c"
uuid = "bac558e1-5e72-5ebc-8fee-abe8a469f55d"
version = "1.4.1"

[[deps.PCRE_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "b2a7af664e098055a7529ad1a900ded962bca488"
uuid = "2f80f16e-611a-54ab-bc61-aa92de5b98fc"
version = "8.44.0+0"

[[deps.Parameters]]
deps = ["OrderedCollections", "UnPack"]
git-tree-sha1 = "34c0e9ad262e5f7fc75b10a9952ca7692cfc5fbe"
uuid = "d96e819e-fc66-5662-9728-84c9c7592b0a"
version = "0.12.3"

[[deps.Parsers]]
deps = ["Dates"]
git-tree-sha1 = "9d8c00ef7a8d110787ff6f170579846f776133a9"
uuid = "69de0a69-1ddd-5017-9359-2bf0b02dc9f0"
version = "2.0.4"

[[deps.Pixman_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "b4f5d02549a10e20780a24fce72bea96b6329e29"
uuid = "30392449-352a-5448-841d-b1acce4e97dc"
version = "0.40.1+0"

[[deps.Pkg]]
deps = ["Artifacts", "Dates", "Downloads", "LibGit2", "Libdl", "Logging", "Markdown", "Printf", "REPL", "Random", "SHA", "Serialization", "TOML", "Tar", "UUIDs", "p7zip_jll"]
uuid = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f"

[[deps.PlotThemes]]
deps = ["PlotUtils", "Requires", "Statistics"]
git-tree-sha1 = "a3a964ce9dc7898193536002a6dd892b1b5a6f1d"
uuid = "ccf2f8ad-2431-5c83-bf29-c5338b663b6a"
version = "2.0.1"

[[deps.PlotUtils]]
deps = ["ColorSchemes", "Colors", "Dates", "Printf", "Random", "Reexport", "Statistics"]
git-tree-sha1 = "2537ed3c0ed5e03896927187f5f2ee6a4ab342db"
uuid = "995b91a9-d308-5afd-9ec6-746e21dbc043"
version = "1.0.14"

[[deps.Plots]]
deps = ["Base64", "Contour", "Dates", "Downloads", "FFMPEG", "FixedPointNumbers", "GR", "GeometryBasics", "JSON", "Latexify", "LinearAlgebra", "Measures", "NaNMath", "PlotThemes", "PlotUtils", "Printf", "REPL", "Random", "RecipesBase", "RecipesPipeline", "Reexport", "Requires", "Scratch", "Showoff", "SparseArrays", "Statistics", "StatsBase", "UUIDs"]
git-tree-sha1 = "457b13497a3ea4deb33d273a6a5ea15c25c0ebd9"
uuid = "91a5bcdd-55d7-5caf-9e0b-520d859cae80"
version = "1.22.2"

[[deps.Preferences]]
deps = ["TOML"]
git-tree-sha1 = "00cfd92944ca9c760982747e9a1d0d5d86ab1e5a"
uuid = "21216c6a-2e73-6563-6e65-726566657250"
version = "1.2.2"

[[deps.Printf]]
deps = ["Unicode"]
uuid = "de0858da-6303-5e67-8744-51eddeeeb8d7"

[[deps.Qt5Base_jll]]
deps = ["Artifacts", "CompilerSupportLibraries_jll", "Fontconfig_jll", "Glib_jll", "JLLWrappers", "Libdl", "Libglvnd_jll", "OpenSSL_jll", "Pkg", "Xorg_libXext_jll", "Xorg_libxcb_jll", "Xorg_xcb_util_image_jll", "Xorg_xcb_util_keysyms_jll", "Xorg_xcb_util_renderutil_jll", "Xorg_xcb_util_wm_jll", "Zlib_jll", "xkbcommon_jll"]
git-tree-sha1 = "ad368663a5e20dbb8d6dc2fddeefe4dae0781ae8"
uuid = "ea2cea3b-5b76-57ae-a6ef-0a8af62496e1"
version = "5.15.3+0"

[[deps.REPL]]
deps = ["InteractiveUtils", "Markdown", "Sockets", "Unicode"]
uuid = "3fa0cd96-eef1-5676-8a61-b3b8758bbffb"

[[deps.Random]]
deps = ["Serialization"]
uuid = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"

[[deps.RecipesBase]]
git-tree-sha1 = "44a75aa7a527910ee3d1751d1f0e4148698add9e"
uuid = "3cdcf5f2-1ef4-517c-9805-6587b60abb01"
version = "1.1.2"

[[deps.RecipesPipeline]]
deps = ["Dates", "NaNMath", "PlotUtils", "RecipesBase"]
git-tree-sha1 = "7ad0dfa8d03b7bcf8c597f59f5292801730c55b8"
uuid = "01d81517-befc-4cb6-b9ec-a95719d0359c"
version = "0.4.1"

[[deps.Reexport]]
git-tree-sha1 = "45e428421666073eab6f2da5c9d310d99bb12f9b"
uuid = "189a3867-3050-52da-a836-e630ba90ab69"
version = "1.2.2"

[[deps.Requires]]
deps = ["UUIDs"]
git-tree-sha1 = "4036a3bd08ac7e968e27c203d45f5fff15020621"
uuid = "ae029012-a4dd-5104-9daa-d747884805df"
version = "1.1.3"

[[deps.SHA]]
uuid = "ea8e919c-243c-51af-8825-aaa63cd721ce"

[[deps.Scratch]]
deps = ["Dates"]
git-tree-sha1 = "0b4b7f1393cff97c33891da2a0bf69c6ed241fda"
uuid = "6c6a2e73-6563-6170-7368-637461726353"
version = "1.1.0"

[[deps.Serialization]]
uuid = "9e88b42a-f829-5b0c-bbe9-9e923198166b"

[[deps.SharedArrays]]
deps = ["Distributed", "Mmap", "Random", "Serialization"]
uuid = "1a1011a3-84de-559e-8e89-a11a2f7dc383"

[[deps.Showoff]]
deps = ["Dates", "Grisu"]
git-tree-sha1 = "91eddf657aca81df9ae6ceb20b959ae5653ad1de"
uuid = "992d4aef-0814-514b-bc4d-f2e9a6c4116f"
version = "1.0.3"

[[deps.Sockets]]
uuid = "6462fe0b-24de-5631-8697-dd941f90decc"

[[deps.SortingAlgorithms]]
deps = ["DataStructures"]
git-tree-sha1 = "b3363d7460f7d098ca0912c69b082f75625d7508"
uuid = "a2af1166-a08f-5f64-846c-94a0d3cef48c"
version = "1.0.1"

[[deps.SparseArrays]]
deps = ["LinearAlgebra", "Random"]
uuid = "2f01184e-e22b-5df5-ae63-d93ebab69eaf"

[[deps.SpecialFunctions]]
deps = ["ChainRulesCore", "LogExpFunctions", "OpenLibm_jll", "OpenSpecFun_jll"]
git-tree-sha1 = "ad42c30a6204c74d264692e633133dcea0e8b14e"
uuid = "276daf66-3868-5448-9aa4-cd146d93841b"
version = "1.6.2"

[[deps.Static]]
deps = ["IfElse"]
git-tree-sha1 = "a8f30abc7c64a39d389680b74e749cf33f872a70"
uuid = "aedffcd0-7271-4cad-89d0-dc628f76c6d3"
version = "0.3.3"

[[deps.StaticArrays]]
deps = ["LinearAlgebra", "Random", "Statistics"]
git-tree-sha1 = "3240808c6d463ac46f1c1cd7638375cd22abbccb"
uuid = "90137ffa-7385-5640-81b9-e52037218182"
version = "1.2.12"

[[deps.Statistics]]
deps = ["LinearAlgebra", "SparseArrays"]
uuid = "10745b16-79ce-11e8-11f9-7d13ad32a3b2"

[[deps.StatsAPI]]
git-tree-sha1 = "1958272568dc176a1d881acb797beb909c785510"
uuid = "82ae8749-77ed-4fe6-ae5f-f523153014b0"
version = "1.0.0"

[[deps.StatsBase]]
deps = ["DataAPI", "DataStructures", "LinearAlgebra", "Missings", "Printf", "Random", "SortingAlgorithms", "SparseArrays", "Statistics", "StatsAPI"]
git-tree-sha1 = "8cbbc098554648c84f79a463c9ff0fd277144b6c"
uuid = "2913bbd2-ae8a-5f71-8c99-4fb6c76f3a91"
version = "0.33.10"

[[deps.StructArrays]]
deps = ["Adapt", "DataAPI", "StaticArrays", "Tables"]
git-tree-sha1 = "2ce41e0d042c60ecd131e9fb7154a3bfadbf50d3"
uuid = "09ab397b-f2b6-538f-b94a-2f83cf4a842a"
version = "0.6.3"

[[deps.TOML]]
deps = ["Dates"]
uuid = "fa267f1f-6049-4f14-aa54-33bafae1ed76"

[[deps.TableTraits]]
deps = ["IteratorInterfaceExtensions"]
git-tree-sha1 = "c06b2f539df1c6efa794486abfb6ed2022561a39"
uuid = "3783bdb8-4a98-5b6b-af9a-565f29a5fe9c"
version = "1.0.1"

[[deps.Tables]]
deps = ["DataAPI", "DataValueInterfaces", "IteratorInterfaceExtensions", "LinearAlgebra", "TableTraits", "Test"]
git-tree-sha1 = "1162ce4a6c4b7e31e0e6b14486a6986951c73be9"
uuid = "bd369af6-aec1-5ad0-b16a-f7cc5008161c"
version = "1.5.2"

[[deps.Tar]]
deps = ["ArgTools", "SHA"]
uuid = "a4e569a6-e804-4fa4-b0f3-eef7a1d5b13e"

[[deps.Test]]
deps = ["InteractiveUtils", "Logging", "Random", "Serialization"]
uuid = "8dfed614-e22c-5e08-85e1-65c5234f0b40"

[[deps.URIs]]
git-tree-sha1 = "97bbe755a53fe859669cd907f2d96aee8d2c1355"
uuid = "5c2747f8-b7ea-4ff2-ba2e-563bfd36b1d4"
version = "1.3.0"

[[deps.UUIDs]]
deps = ["Random", "SHA"]
uuid = "cf7118a7-6976-5b1a-9a39-7adc72f591a4"

[[deps.UnPack]]
git-tree-sha1 = "387c1f73762231e86e0c9c5443ce3b4a0a9a0c2b"
uuid = "3a884ed6-31ef-47d7-9d2a-63182c4928ed"
version = "1.0.2"

[[deps.Unicode]]
uuid = "4ec0a83e-493e-50e2-b9ac-8f72acf5a8f5"

[[deps.Wayland_jll]]
deps = ["Artifacts", "Expat_jll", "JLLWrappers", "Libdl", "Libffi_jll", "Pkg", "XML2_jll"]
git-tree-sha1 = "3e61f0b86f90dacb0bc0e73a0c5a83f6a8636e23"
uuid = "a2964d1f-97da-50d4-b82a-358c7fce9d89"
version = "1.19.0+0"

[[deps.Wayland_protocols_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Wayland_jll"]
git-tree-sha1 = "2839f1c1296940218e35df0bbb220f2a79686670"
uuid = "2381bf8a-dfd0-557d-9999-79630e7b1b91"
version = "1.18.0+4"

[[deps.XML2_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Libiconv_jll", "Pkg", "Zlib_jll"]
git-tree-sha1 = "1acf5bdf07aa0907e0a37d3718bb88d4b687b74a"
uuid = "02c8fc9c-b97f-50b9-bbe4-9be30ff0a78a"
version = "2.9.12+0"

[[deps.XSLT_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Libgcrypt_jll", "Libgpg_error_jll", "Libiconv_jll", "Pkg", "XML2_jll", "Zlib_jll"]
git-tree-sha1 = "91844873c4085240b95e795f692c4cec4d805f8a"
uuid = "aed1982a-8fda-507f-9586-7b0439959a61"
version = "1.1.34+0"

[[deps.Xorg_libX11_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_libxcb_jll", "Xorg_xtrans_jll"]
git-tree-sha1 = "5be649d550f3f4b95308bf0183b82e2582876527"
uuid = "4f6342f7-b3d2-589e-9d20-edeb45f2b2bc"
version = "1.6.9+4"

[[deps.Xorg_libXau_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "4e490d5c960c314f33885790ed410ff3a94ce67e"
uuid = "0c0b7dd1-d40b-584c-a123-a41640f87eec"
version = "1.0.9+4"

[[deps.Xorg_libXcursor_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_libXfixes_jll", "Xorg_libXrender_jll"]
git-tree-sha1 = "12e0eb3bc634fa2080c1c37fccf56f7c22989afd"
uuid = "935fb764-8cf2-53bf-bb30-45bb1f8bf724"
version = "1.2.0+4"

[[deps.Xorg_libXdmcp_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "4fe47bd2247248125c428978740e18a681372dd4"
uuid = "a3789734-cfe1-5b06-b2d0-1dd0d9d62d05"
version = "1.1.3+4"

[[deps.Xorg_libXext_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_libX11_jll"]
git-tree-sha1 = "b7c0aa8c376b31e4852b360222848637f481f8c3"
uuid = "1082639a-0dae-5f34-9b06-72781eeb8cb3"
version = "1.3.4+4"

[[deps.Xorg_libXfixes_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_libX11_jll"]
git-tree-sha1 = "0e0dc7431e7a0587559f9294aeec269471c991a4"
uuid = "d091e8ba-531a-589c-9de9-94069b037ed8"
version = "5.0.3+4"

[[deps.Xorg_libXi_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_libXext_jll", "Xorg_libXfixes_jll"]
git-tree-sha1 = "89b52bc2160aadc84d707093930ef0bffa641246"
uuid = "a51aa0fd-4e3c-5386-b890-e753decda492"
version = "1.7.10+4"

[[deps.Xorg_libXinerama_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_libXext_jll"]
git-tree-sha1 = "26be8b1c342929259317d8b9f7b53bf2bb73b123"
uuid = "d1454406-59df-5ea1-beac-c340f2130bc3"
version = "1.1.4+4"

[[deps.Xorg_libXrandr_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_libXext_jll", "Xorg_libXrender_jll"]
git-tree-sha1 = "34cea83cb726fb58f325887bf0612c6b3fb17631"
uuid = "ec84b674-ba8e-5d96-8ba1-2a689ba10484"
version = "1.5.2+4"

[[deps.Xorg_libXrender_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_libX11_jll"]
git-tree-sha1 = "19560f30fd49f4d4efbe7002a1037f8c43d43b96"
uuid = "ea2f1a96-1ddc-540d-b46f-429655e07cfa"
version = "0.9.10+4"

[[deps.Xorg_libpthread_stubs_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "6783737e45d3c59a4a4c4091f5f88cdcf0908cbb"
uuid = "14d82f49-176c-5ed1-bb49-ad3f5cbd8c74"
version = "0.1.0+3"

[[deps.Xorg_libxcb_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "XSLT_jll", "Xorg_libXau_jll", "Xorg_libXdmcp_jll", "Xorg_libpthread_stubs_jll"]
git-tree-sha1 = "daf17f441228e7a3833846cd048892861cff16d6"
uuid = "c7cfdc94-dc32-55de-ac96-5a1b8d977c5b"
version = "1.13.0+3"

[[deps.Xorg_libxkbfile_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_libX11_jll"]
git-tree-sha1 = "926af861744212db0eb001d9e40b5d16292080b2"
uuid = "cc61e674-0454-545c-8b26-ed2c68acab7a"
version = "1.1.0+4"

[[deps.Xorg_xcb_util_image_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_xcb_util_jll"]
git-tree-sha1 = "0fab0a40349ba1cba2c1da699243396ff8e94b97"
uuid = "12413925-8142-5f55-bb0e-6d7ca50bb09b"
version = "0.4.0+1"

[[deps.Xorg_xcb_util_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_libxcb_jll"]
git-tree-sha1 = "e7fd7b2881fa2eaa72717420894d3938177862d1"
uuid = "2def613f-5ad1-5310-b15b-b15d46f528f5"
version = "0.4.0+1"

[[deps.Xorg_xcb_util_keysyms_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_xcb_util_jll"]
git-tree-sha1 = "d1151e2c45a544f32441a567d1690e701ec89b00"
uuid = "975044d2-76e6-5fbe-bf08-97ce7c6574c7"
version = "0.4.0+1"

[[deps.Xorg_xcb_util_renderutil_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_xcb_util_jll"]
git-tree-sha1 = "dfd7a8f38d4613b6a575253b3174dd991ca6183e"
uuid = "0d47668e-0667-5a69-a72c-f761630bfb7e"
version = "0.3.9+1"

[[deps.Xorg_xcb_util_wm_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_xcb_util_jll"]
git-tree-sha1 = "e78d10aab01a4a154142c5006ed44fd9e8e31b67"
uuid = "c22f9ab0-d5fe-5066-847c-f4bb1cd4e361"
version = "0.4.1+1"

[[deps.Xorg_xkbcomp_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_libxkbfile_jll"]
git-tree-sha1 = "4bcbf660f6c2e714f87e960a171b119d06ee163b"
uuid = "35661453-b289-5fab-8a00-3d9160c6a3a4"
version = "1.4.2+4"

[[deps.Xorg_xkeyboard_config_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_xkbcomp_jll"]
git-tree-sha1 = "5c8424f8a67c3f2209646d4425f3d415fee5931d"
uuid = "33bec58e-1273-512f-9401-5d533626f822"
version = "2.27.0+4"

[[deps.Xorg_xtrans_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "79c31e7844f6ecf779705fbc12146eb190b7d845"
uuid = "c5fb5394-a638-5e4d-96e5-b29de1b5cf10"
version = "1.4.0+3"

[[deps.Zlib_jll]]
deps = ["Libdl"]
uuid = "83775a58-1f1d-513f-b197-d71354ab007a"

[[deps.Zstd_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "cc4bf3fdde8b7e3e9fa0351bdeedba1cf3b7f6e6"
uuid = "3161d3a3-bdf6-5164-811a-617609db77b4"
version = "1.5.0+0"

[[deps.libass_jll]]
deps = ["Artifacts", "Bzip2_jll", "FreeType2_jll", "FriBidi_jll", "HarfBuzz_jll", "JLLWrappers", "Libdl", "Pkg", "Zlib_jll"]
git-tree-sha1 = "5982a94fcba20f02f42ace44b9894ee2b140fe47"
uuid = "0ac62f75-1d6f-5e53-bd7c-93b484bb37c0"
version = "0.15.1+0"

[[deps.libblastrampoline_jll]]
deps = ["Artifacts", "Libdl", "OpenBLAS_jll"]
uuid = "8e850b90-86db-534c-a0d3-1478176c7d93"

[[deps.libfdk_aac_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "daacc84a041563f965be61859a36e17c4e4fcd55"
uuid = "f638f0a6-7fb0-5443-88ba-1cc74229b280"
version = "2.0.2+0"

[[deps.libpng_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Zlib_jll"]
git-tree-sha1 = "94d180a6d2b5e55e447e2d27a29ed04fe79eb30c"
uuid = "b53b4c65-9356-5827-b1ea-8c7a1a84506f"
version = "1.6.38+0"

[[deps.libvorbis_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Ogg_jll", "Pkg"]
git-tree-sha1 = "c45f4e40e7aafe9d086379e5578947ec8b95a8fb"
uuid = "f27f6e37-5d2b-51aa-960f-b287f2bc3b7a"
version = "1.3.7+0"

[[deps.nghttp2_jll]]
deps = ["Artifacts", "Libdl"]
uuid = "8e850ede-7688-5339-a07c-302acd2aaf8d"

[[deps.p7zip_jll]]
deps = ["Artifacts", "Libdl"]
uuid = "3f19e933-33d8-53b3-aaab-bd5110c3b7a0"

[[deps.x264_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "4fea590b89e6ec504593146bf8b988b2c00922b2"
uuid = "1270edf5-f2f9-52d2-97e9-ab00b5d0237a"
version = "2021.5.5+0"

[[deps.x265_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "ee567a171cce03570d77ad3a43e90218e38937a9"
uuid = "dfaa095f-4041-5dcd-9319-2fabd8486b76"
version = "3.5.0+0"

[[deps.xkbcommon_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Wayland_jll", "Wayland_protocols_jll", "Xorg_libxcb_jll", "Xorg_xkeyboard_config_jll"]
git-tree-sha1 = "ece2350174195bb31de1a63bea3a41ae1aa593b6"
uuid = "d8fb68d0-12a3-5cfd-a85a-d49703b185fd"
version = "0.9.1+5"
"""

# ╔═╡ Cell order:
# ╟─21305de4-1efd-11ec-071a-fd5d4d81dd65
# ╠═9e164dc1-55f8-4f75-b050-3f566f3cf328
# ╟─50aedf4c-904a-4ef3-a113-6f21c6fc2d33
# ╟─4c2ed0bd-ea08-495c-94c5-2c7e92ff29d6
# ╠═d3588870-17f8-467b-928b-1b6781218296
# ╠═3fc5c2e0-d05f-400c-a250-6fb7207ff250
# ╟─688b2980-43d3-4df1-825a-2da885beb08f
# ╠═bd298666-6284-4b63-a217-1a0d46f2d7af
# ╟─8de162b4-2a13-48c1-b9e9-133035d842ce
# ╟─e08458c6-78f3-4b34-b8ba-79dd83441f68
# ╠═74375a4a-8aea-43e3-b293-562ae8d5c114
# ╟─2b611f9e-17c7-45d3-ba04-5563e9bb7ed3
# ╟─586ecaf0-6a36-468f-998c-d22cbb869990
# ╠═b147630e-e17e-48ca-8733-a0588f6e6d3b
# ╟─293dea21-2128-41d3-b11c-47225d27d168
# ╟─344724c5-f849-4234-aa21-2c6e48a042c0
# ╠═4dafb136-cadb-4689-8511-01b72b308515
# ╟─957c5d5f-df77-463e-8cc8-3affec13a636
# ╟─f0559c7f-83ed-4797-8fe1-d87ed27419fa
# ╟─293407bc-2958-407f-b82b-d28f94023b60
# ╠═02ef58f1-235a-4108-917d-5c2e7e0527a1
# ╟─c00f201c-b2b9-4226-ae7f-82269a399199
# ╠═fb414e6a-52ee-419c-b2dc-c320c27f17e2
# ╟─c0a78db4-794e-48f8-a34d-d7fcbddb279b
# ╟─8825a1ac-5c1c-47fb-b16d-aade27463ad3
# ╠═1e4def72-64a4-4b2e-bf0f-86a4ee57bc10
# ╟─a37aa68d-f4ff-4fb2-b8d2-ff80bd67b6a1
# ╟─690dbae8-a720-4d51-87a2-7834d84ee60b
# ╠═14baffbc-2cf0-4b6c-8b35-bfaf0605575c
# ╟─99b7cb68-508a-40ad-9007-4fbe9eb676ce
# ╠═7e3b1dd7-dfc7-48b8-9c0d-9d71d8d3ea62
# ╟─a89a5fee-a28d-43df-be08-a146c476a5db
# ╠═c1c0ea70-fc6b-4928-adff-e58edd22d7e0
# ╟─f5c664fc-9877-4800-b261-d9233d4c006a
# ╟─b796ff78-0741-42b3-8285-b01a042feabc
# ╟─a8242689-1552-4261-b1b8-767fa80b74ea
# ╠═1c422e7a-3e59-4b4a-af58-cfb1e5818c53
# ╟─778c181e-7253-4666-9075-14aa9f0315fa
# ╠═d2f5d13a-cd95-42e4-b6b8-d60e4057f93a
# ╟─00000000-0000-0000-0000-000000000001
# ╟─00000000-0000-0000-0000-000000000002


text:
using Revise, Test

module BackEdgesTest
flag = false    # this needs to be defined for the conditional part to work
end

@testset "Backedges" begin
    src = """
    # issue #249
    flag = false
    if flag
        f() = 1
    else
        f() = 2
    end

    # don't do work in the interpreter that isn't needed for function definitions
    # inspired by #300
    const planetdiameters = Dict("Mercury" => 4_878)
    planetdiameters["Venus"] = 12_104

    function getdiameter(name)
        return planetdiameters[name]
    end
    """
    mexs = Revise.parse_source!(Revise.ModuleExprsSigs(BackEdgesTest), src, "backedges_test.jl", BackEdgesTest)
    Revise.moduledeps[BackEdgesTest] = Revise.DepDict()
    Revise.instantiate_sigs!(mexs)
    @test isempty(methods(BackEdgesTest.getdiameter))
    @test !isdefined(BackEdgesTest, :planetdiameters)
    @test length(Revise.moduledeps[BackEdgesTest]) == 1
    @test Revise.moduledeps[BackEdgesTest][:flag] == Set([(BackEdgesTest, first(Iterators.drop(mexs[BackEdgesTest], 1))[1])])
end


text:
using Documenter
using DeIdentification

# auth = GitHub.authenticate(ENV["GITHUB_AUTH"])

# make assets dir if doesn't exist
assets_dir = joinpath(@__DIR__,"src","assets")
if !isdir(assets_dir)
    mkdir(assets_dir)
end

base_url = "https://raw.githubusercontent.com/bcbi/code_style_guide/master/assets/"

# get/replace favicon
favicon_url = base_url*"favicon.ico"
favicon_path = joinpath(assets_dir,"favicon.ico")
run(`curl -g -L -f -o $favicon_path $favicon_url`)

# get/replace css
css_url = base_url*"bcbi.css"
css_path = joinpath(assets_dir,"bcbi.css")
run(`curl -g -L -f -o $css_path $css_url`)

# get/replace logo
logo_url = base_url*"bcbi-white-v.png"
logo_path = joinpath(assets_dir,"logo.png")
run(`curl -g -L -f -o $logo_path $logo_url`)

makedocs(
    modules = [ DeIdentification ],
    assets = [
        "assets/favicon.ico",
        "assets/bcbi.css",
        "assets/logo.png"
        ],
    sitename = "DeIdentification.jl",
    debug = true,
    pages = [
        "Home" => "index.md",
        "Guide" => "usage.md",
        "API" => "documentation.md"
        ]
    )

deploydocs(
    repo = "github.com/bcbi/DeIdentification.jl.git"
)


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

using Manifolds: induced_basis

@testset "Euclidean" begin
    E = Euclidean(3)
    Ec = Euclidean(3; field=ℂ)
    EM = Manifolds.MetricManifold(E, Manifolds.EuclideanMetric())
    @test repr(E) == "Euclidean(3; field = ℝ)"
    @test repr(Ec) == "Euclidean(3; field = ℂ)"
    @test repr(Euclidean(2, 3; field=ℍ)) == "Euclidean(2, 3; field = ℍ)"
    @test Manifolds.allocation_promotion_function(Ec, get_vector, ()) === complex
    p = zeros(3)
    A = Manifolds.RetractionAtlas()
    B = induced_basis(EM, A, p, TangentSpace)
    @test det_local_metric(EM, p, B) == one(eltype(p))
    @test log_local_metric_density(EM, p, B) == zero(eltype(p))
    @test project!(E, p, p) == p
    @test embed!(E, p, p) == p
    @test manifold_dimension(Ec) == 2 * manifold_dimension(E)
    X = zeros(3)
    X[1] = 1.0
    Y = similar(X)
    project!(E, Y, p, X)
    @test Y == X
    @test embed(E, p, X) == X

    # temp: explicit test for induced basis
    B = induced_basis(E, RetractionAtlas(), 0, ManifoldsBase.TangentSpaceType())
    @test get_coordinates(E, p, X, B) == X
    get_coordinates!(E, Y, p, X, B)
    @test Y == X
    @test get_vector(E, p, Y, B) == X
    Y2 = similar(X)
    get_vector!(E, Y2, p, Y, B)
    @test Y2 == X

    Y = parallel_transport_along(E, p, X, [p])
    @test Y == X
    parallel_transport_along!(E, Y, p, X, [p])
    @test Y == X

    Y = vector_transport_along(E, p, X, [p])
    @test Y == X
    vector_transport_along!(E, Y, p, X, [p])
    @test Y == X

    # real manifold does not allow complex values
    @test_throws DomainError is_point(Ec, [:a, :b, :b], true)
    @test_throws DomainError is_point(E, [1.0, 1.0im, 0.0], true)
    @test_throws DomainError is_point(E, [1], true)
    @test_throws DomainError is_vector(Ec, [:a, :b, :b], [1.0, 1.0, 0.0], true)
    @test_throws DomainError is_vector(E, [1.0, 1.0im, 0.0], [1.0, 1.0, 0.0], true) # real manifold does not allow complex values
    @test_throws DomainError is_vector(E, [1], [1.0, 1.0, 0.0], true)
    @test_throws DomainError is_vector(E, [0.0, 0.0, 0.0], [1.0], true)
    @test_throws DomainError is_vector(E, [0.0, 0.0, 0.0], [1.0, 0.0, 1.0im], true)
    @test_throws DomainError is_vector(Ec, [0.0, 0.0, 0.0], [:a, :b, :c], true)

    @test E^2 === Euclidean(3, 2)
    @test ^(E, 2) === Euclidean(3, 2)
    @test E^(2,) === Euclidean(3, 2)
    @test Ec^(4, 5) === Euclidean(3, 4, 5; field=ℂ)

    manifolds = [E, EM, Ec]
    types = [Vector{Float64}]
    TEST_FLOAT32 && push!(types, Vector{Float32})
    TEST_DOUBLE64 && push!(types, Vector{Double64})
    TEST_STATIC_SIZED && push!(types, MVector{3,Float64})

    types_complex = [Vector{ComplexF64}]
    TEST_FLOAT32 && push!(types_complex, Vector{ComplexF32})
    TEST_DOUBLE64 && push!(types_complex, Vector{ComplexDF64})
    TEST_STATIC_SIZED && push!(types_complex, MVector{3,ComplexF64})

    for M in manifolds
        basis_types = if M == E
            (
                DefaultOrthonormalBasis(),
                ProjectedOrthonormalBasis(:svd),
                DiagonalizingOrthonormalBasis([1.0, 2.0, 3.0]),
            )
        elseif M == Ec
            (
                DefaultOrthonormalBasis(),
                DefaultOrthonormalBasis(ℂ),
                DiagonalizingOrthonormalBasis([1.0, 2.0, 3.0]),
                DiagonalizingOrthonormalBasis([1.0, 2.0, 3.0], ℂ),
            )
        else
            ()
        end
        for T in types
            @testset "$M Type $T" begin
                pts = [
                    convert(T, [1.0, 0.0, 0.0]),
                    convert(T, [0.0, 1.0, 0.0]),
                    convert(T, [0.0, 0.0, 1.0]),
                ]
                test_manifold(
                    M,
                    pts,
                    test_project_point=true,
                    test_project_tangent=true,
                    test_musical_isomorphisms=true,
                    test_default_vector_transport=true,
                    vector_transport_methods=[
                        ParallelTransport(),
                        SchildsLadderTransport(),
                        PoleLadderTransport(),
                    ],
                    test_mutating_rand=isa(T, Vector),
                    point_distributions=[
                        Manifolds.projected_distribution(
                            M,
                            Distributions.MvNormal(zero(pts[1]), 1.0),
                        ),
                    ],
                    tvector_distributions=[
                        Manifolds.normal_tvector_distribution(M, pts[1], 1.0),
                    ],
                    basis_types_vecs=basis_types,
                    basis_types_to_from=basis_types,
                    basis_has_specialized_diagonalizing_get=true,
                    test_vee_hat=isa(M, Euclidean),
                    test_inplace=true,
                    test_rand_point=M === E,
                    test_rand_tvector=M === E,
                )
            end
        end
    end
    for T in types_complex
        @testset "Complex Euclidean, type $T" begin
            pts = [
                convert(T, [1.0im, -1.0im, 1.0]),
                convert(T, [0.0, 1.0, 1.0im]),
                convert(T, [0.0, 0.0, 1.0]),
            ]
            test_manifold(
                Ec,
                pts,
                test_project_tangent=true,
                test_musical_isomorphisms=true,
                test_default_vector_transport=true,
                test_vee_hat=false,
                parallel_transport=true,
            )
        end
    end

    number_types = [Float64, ComplexF64]
    TEST_FLOAT32 && push!(number_types, Float32)
    @testset "(Nonmutating) Real and Complex Numbers" begin
        RM = Euclidean()
        CM = Euclidean(; field=ℂ)
        for T in number_types
            @testset "Type $T" begin
                M = (T <: Complex) ? CM : RM
                pts = convert.(Ref(T), [1.0, 4.0, 2.0])
                @test embed(M, pts[1]) == pts[1]
                @test project(M, pts[1]) == pts[1]
                @test retract(M, pts[1], pts[2]) == exp(M, pts[1], pts[2])
                test_manifold(
                    M,
                    pts,
                    test_vector_spaces=false,
                    test_project_tangent=true,
                    test_musical_isomorphisms=true,
                    test_default_vector_transport=true,
                    test_vee_hat=false,
                    is_mutating=false,
                )
            end
        end
    end

    @testset "hat/vee" begin
        E = Euclidean(3, 2)
        p = collect(reshape(1.0:6.0, (3, 2)))
        X = collect(reshape(7.0:12.0, (3, 2)))
        @test hat(E, p, vec(X)) ≈ X
        Y = allocate(X)
        @test hat!(E, Y, p, vec(X)) === Y
        @test Y ≈ X
        @test vee(E, p, X) ≈ vec(X)
        Y = allocate(vec(X))
        @test vee!(E, Y, p, X) === Y
        @test Y ≈ vec(X)
    end

    @testset "Number systems power" begin
        @test ℝ^2 === Euclidean(2)
        @test ℝ^(2, 3) === Euclidean(2, 3)

        @test ℂ^2 === Euclidean(2; field=ℂ)
        @test ℂ^(2, 3) === Euclidean(2, 3; field=ℂ)

        @test ℍ^2 === Euclidean(2; field=ℍ)
        @test ℍ^(2, 3) === Euclidean(2, 3; field=ℍ)
    end

    @testset "Embeddings into larger Euclidean Manifolds" begin
        M = Euclidean(3, 3)
        N = Euclidean(4, 4)
        O = EmbeddedManifold(M, N)
        # first test with same length of sizes
        p = ones(3, 3)
        q = zeros(4, 4)
        qT = zeros(4, 4)
        qT[1:3, 1:3] .= 1.0
        embed!(O, q, p)
        @test norm(qT - q) == 0
        qM = embed(O, p)
        @test norm(project(O, qM) - p) == 0
        @test norm(qT - qM) == 0
        # test with different sizes, check that it only fills first element
        q2 = zeros(4, 4, 3)
        q2T = zeros(4, 4, 3)
        q2T[1:3, 1:3, 1] .= 1.0
        embed!(O, q2, p)
        @test norm(q2T - q2) == 0
        O2 = EmbeddedManifold(M, Euclidean(4, 4, 3))
        q2M = embed(O2, p)
        @test norm(q2T - q2M) == 0
        # wrong size error checks
        @test_throws DomainError embed!(O, zeros(3, 3), zeros(3, 3, 5))
        @test_throws DomainError embed!(O, zeros(3, 3), zeros(4, 4))
        @test_throws DomainError project!(O, zeros(3, 3, 5), zeros(3, 3))
        @test_throws DomainError project!(O, zeros(4, 4), zeros(3, 3))
    end

    @testset "Embedding Real into Complex" begin
        M = Euclidean(3, 3)
        N = Euclidean(3, 4; field=ℂ)
        O = EmbeddedManifold(M, N)
        p = ones(3, 3)
        qT = zeros(ComplexF64, 3, 4)
        qT[1:3, 1:3] .= 1.0
        q = embed(O, p)
        @test is_point(N, q)
        @test q == qT
        q2 = zeros(ComplexF64, 3, 4)
        embed!(O, q2, p)
        @test q2 == qT
    end

    @testset "Euclidean metric tests" begin
        M = Euclidean(2)
        p = zeros(2)
        A = Manifolds.get_default_atlas(M)
        i = Manifolds.get_chart_index(M, A, p)
        B = Manifolds.induced_basis(M, A, i, TangentSpace)
        C1 = christoffel_symbols_first(M, p, B)
        @test size(C1) == (2, 2, 2)
        @test norm(C1) ≈ 0.0 atol = 1e-13
        C2 = christoffel_symbols_second(M, p, B)
        @test size(C2) == (2, 2, 2)
        @test norm(C2) ≈ 0.0 atol = 1e-13
        C2j = christoffel_symbols_second_jacobian(M, p, B)
        @test size(C2j) == (2, 2, 2, 2)
        @test norm(C2j) ≈ 0.0 atol = 1e-16
        @test einstein_tensor(M, p, B) == zeros(2, 2)
        @test ricci_curvature(M, p, B) ≈ 0 atol = 1e-16
        RC = ricci_tensor(M, p, B)
        @test size(RC) == (2, 2)
        @test norm(RC) ≈ 0.0 atol = 1e-16
        @test local_metric(M, p, B) == Diagonal(ones(2))
        @test inverse_local_metric(M, p, B) == Diagonal(ones(2))
        @test det_local_metric(M, p, B) == 1
        RT = riemann_tensor(M, p, B)
        @test size(RT) == (2, 2, 2, 2)
        @test norm(RT) ≈ 0.0 atol = 1e-16
    end
    @testset "Induced Basis and local metric for EuclideanMetric" begin
        struct DefaultManifold <: AbstractManifold{ℝ} end
        p = zeros(3)
        M = DefaultManifold()
        TpM = TangentSpace(M, p)
        B = induced_basis(M, Manifolds.get_default_atlas(M), p, TangentSpace)
        MM = MetricManifold(M, EuclideanMetric())
        @test local_metric(MM, p, B) == Diagonal(ones(3))
        @test inverse_local_metric(MM, p, B) == Diagonal(ones(3))
        @test det_local_metric(MM, p, B) == 1.0
        DB1 = dual_basis(MM, p, B)
        @test DB1 isa InducedBasis
        @test DB1.vs isa ManifoldsBase.CotangentSpaceType
        DB2 = induced_basis(M, Manifolds.get_default_atlas(M), p, CotangentSpace)
        @test DB2 isa InducedBasis
        @test DB2.vs isa ManifoldsBase.CotangentSpaceType
        DDB = dual_basis(MM, p, DB2)
        @test DDB isa InducedBasis
        @test DDB.vs isa ManifoldsBase.TangentSpaceType
    end
    @testset "RNG point with σ" begin
        @test is_point(E, rand(E; σ=10.0))
        @test is_point(E, rand(MersenneTwister(123), E; σ=10.0))
    end
end


text:
using Documenter, Desktop

makedocs(;
    format=Documenter.HTML(),
    pages=[
        "Home" => "index.md",
    ],
    repo="https://github.com/mgkuhn/Desktop.jl/blob/{commit}{path}#L{line}",
    sitename="Desktop.jl",
    authors="Markus Kuhn",
)

deploydocs(;
    repo="github.com/mgkuhn/Desktop.jl",
)


text:
# test the functions in src/bootstrap.jl

exdir = joinpath(@__DIR__,"..","examples")
# exdir = joinpath(dirname(pathof(PhyloNetworks)), "..","examples")

@testset "testing hybridBootstrapSupport" begin
bestnet = readTopology(joinpath(exdir,"fish2hyb.net"));
bootnet = readMultiTopology(joinpath(exdir,"fish3hyb_20boostrap.net"));
# issues with bootstrap networks 12, 21, 42, 96
# plot(bootnet[20], showEdgeNumber=true)
# include(string(home, "bootstrap.jl"))
resn, rese, resc, gam, edgenum = hybridBootstrapSupport(bootnet,bestnet);
#@show resn; @show rese; showall(gam); @show edgenum; resc
# plot(bestnet, showIntNodeNumber=true)

@test resn[1:2,:clade] == ["H26","H25"]
@test resn[1:2,:BS_hybrid_samesisters] == [25.0,100.0]
@test resn[!,:BS_hybrid] == [100.0,100,0,0,0,75,0,0,0,0,0,0,5,5,5,5,5,0,0,0]
@test resn[!,:BS_minor_sister] == [0.0,0,100,0,0,5,10,70,75,25,5,5,0,0,0,0,0,0,0,5]
@test resn[!,:BS_major_sister] == [0.0,0,0,100,100,0,70,10,0,0,5,5,0,0,0,0,0,5,5,0]
@test rese[2,:BS_minor] == 25.0  # BS of introgression for H26
@test rese[4,:BS_minor] == 100.0 # BS of introgression for H25
@test resc[!,:taxa]==["Xgordoni","Xmeyeri","Xcouchianus","Xvariatus","Xevelynae","Xxiphidium",
 "Xmilleri","Xandersi","Xmaculatus","Xhellerii","Xalvarezi","Xmayae","Xsignum","Xclemenciae_F2",
 "Xmonticolus","Xmontezumae","Xnezahuacoyotl","Xbirchmanni_GARC","Xmalinche_CHIC2","Xcortezi",
 "Xcontinens","Xpygmaeus","Xnigrensis","Xmultilineatus"]
@test resc[!,:taxa][resc[!,:H26]] == ["Xnezahuacoyotl"]
@test resc[!,:taxa][resc[!,:H25]] == ["Xmontezumae","Xnezahuacoyotl","Xbirchmanni_GARC","Xmalinche_CHIC2","Xcortezi","Xcontinens","Xpygmaeus","Xnigrensis","Xmultilineatus"]
@test resc[!,:taxa][resc[!,:c_minus27]] == ["Xnigrensis","Xmultilineatus"] # minor sis of H26
@test resc[!,:taxa][resc[!,:Xxiphidium]] == ["Xxiphidium"] # minor sis of H25
@test resc[!,:taxa][resc[!,:Xsignum]] == ["Xsignum"] # donor8 previously
@test resc[!,:taxa][resc[!,:c_minus24]] == ["Xcontinens","Xpygmaeus","Xnigrensis","Xmultilineatus"] # donor7
@test resc[!,:taxa][resc[!,:Xmontezumae]] == ["Xmontezumae"] # major sis of H26. Below: major sis of H25
@test resc[!,:taxa][resc[!,:c_minus12]] == ["Xhellerii","Xalvarezi","Xmayae","Xsignum","Xclemenciae_F2","Xmonticolus"]
@test gam[:,2] == [.0,.0,.192,.0,.0,.0,.0,.0,.193,.0,.184,.193,.0,.0,.0,.0,.0,.193,.0,.0]
@test gam[:,4] == [.165,.166,.165,.166,.165,.165,.166,.165,.165,.166,.164,.166,.166,.165,.165,.165,.166,.165,.166,.166]
@test edgenum ==[25,39,43,7]
end # of testset, hybridBootstrapSupport

@testset "bootsnaq from quartet CF intervals" begin
T=readTopology(joinpath(exdir,"startTree.txt"))
datf=DataFrame(CSV.File(joinpath(exdir,"tableCFCI.csv")); copycols=false)
originalstdout = stdout
redirect_stdout(devnull) # requires julia v1.6
bootnet = bootsnaq(T,datf,nrep=2,runs=1,seed=1234,filename="",Nfail=2,
                   ftolAbs=1e-3,ftolRel=1e-3,xtolAbs=1e-4,xtolRel=1e-3,liktolAbs=0.01)
redirect_stdout(originalstdout)
@test size(bootnet)==(2,)
@test writeTopology(bootnet[1], round=true)=="(4,(((6,#H7:0.0::0.222):10.0,2):0.0,((5,1):0.0)#H7:0.0::0.778):0.0,3);"
@test writeTopology(bootnet[2], round=true)=="(2,3,((4,5):0.0,(1,6):0.011):0.0);"
# "(2,((5,#H9:0.0::0.298):3.927,3):1.331,(((1,6):0.019,4):0.0)#H9:0.0::0.702);"
# above: bad diamond 2, and both edges above the hybrid have estimated length of 0.0...
end

@testset "bootsnaq from bootstrap gene trees, multiple procs" begin
treefile = joinpath(exdir,"treefile.txt") # pretending these are bootstrap trees, for all genes
boottrees = Vector{HybridNetwork}[]
T=readTopology(joinpath(exdir,"startTree.txt"))
net1 = readTopology("(5,(((2,(1)#H7:::0.7143969494428192):1.5121337017411736,4):0.4894187322508883,3):0.519160762355313,(6,#H7:::0.2856030505571808):10.0);")
for i=1:13 push!(boottrees, readMultiTopology(treefile)) end
for i=1:13 @test size(boottrees[i])==(10,) end # 10 bootstrap trees for each of 13 "genes"
addprocs(1)
@everywhere using PhyloNetworks
# using Distributed; @everywhere begin; using Pkg; Pkg.activate("."); using PhyloNetworks; end
originalstdout = stdout
redirect_stdout(devnull)
bootnet = bootsnaq(T,boottrees,nrep=2,runs=2,otherNet=net1,seed=1234,
                   prcnet=0.5,filename="",Nfail=2,ftolAbs=1e-3,ftolRel=1e-3)
redirect_stdout(originalstdout)
rmprocs(workers())
@test size(bootnet)==(2,)
@test all(n -> n.numHybrids==1, bootnet)
@test writeTopology(bootnet[1], round=true, digits=1) != writeTopology(bootnet[2], round=true, digits=1)
filelist = joinpath(exdir, "treefilelist.txt")
boottrees = readBootstrapTrees(filelist)
@test length(boottrees) == 2
@test [length(b) for b in boottrees] == [10, 10]
end


text:
using Oceananigans

include("utils.jl")

Nx, Ny, Nz = 128, 128, 1
Lx, Ly, Lz = 2000, 2000, 10
Nt, Δt = 25, 1

model = Model(N=(Nx, Ny, Nz), L=(Lx, Ly, Lz), ν=4e-2, κ=4e-2)

@. model.tracers.T.data[70:90, 10:30, 1] += 0.01
# @. model.velocities.u.data = 0.1
# @. model.velocities.v.data = 0.1

# Add a NetCDF output writer that saves NetCDF files to the current directory
# "." with a filename prefix of "vertical_profile_" every 200 iterations.
nc_writer = NetCDFOutputWriter(dir=".", prefix="barotropic_tracer_", frequency=1)
push!(model.output_writers, nc_writer)

time_step!(model, Nt, Δt)

make_horizontal_slice_movie(model, nc_writer, "T", Nt, Δt, model.eos.T₀)