text:
"""This module wraps the rust pacosako dynamic library"""
module JtacPacoSako

using Jtac

# PacoSako game type
export PacoSako

# export Jtac interface
export Jtac,
       Util,
       Game,
       Model,
       Player,
       Training,
       Bench

# To build this, run `cargo build` in ../lib
# const DYNLIB_PATH = "../lib/target/debug/libpacosako.so"
# To build this, run `cargo build --release` in ../lib
const DYNLIB_PATH = joinpath(dirname(@__DIR__), "../lib/target/release/libpacosako.so")

mutable struct PacoSako <: Game.AbstractGame
    ptr::Ptr{Nothing}
    cache::Union{Nothing,Vector{UInt8}} # store serialized game when frozen
    forfeit_by::Int64
end

"""Initializer and general memory management"""
function PacoSako()::PacoSako
    ptr = ccall((:new, DYNLIB_PATH), Ptr{Nothing}, ())
    wrap_pacosako_ptr(ptr)
end

function wrap_pacosako_ptr(ptr::Ptr{Nothing})::PacoSako
    ps = PacoSako(ptr, nothing, 0)
    finalizer(destroy!, ps)
    ps
end

"""Destructor. Never call that manually, or you'll double free / use after free."""
function destroy!(ps::PacoSako)
    # ccall to rust to tell it to release the object.
    ccall((:drop, DYNLIB_PATH), Nothing, (Ptr{Nothing},), ps.ptr)
end

################################################################################
## Implementation of the Game interface. #######################################
################################################################################

function Base.copy(ps::PacoSako)::PacoSako
    @assert !Game.is_frozen(ps)
    ptr = ccall((:clone, DYNLIB_PATH), Ptr{Nothing}, (Ptr{Nothing},), ps.ptr)
    ps2 = wrap_pacosako_ptr(ptr)
    ps2.forfeit_by = ps.forfeit_by
    ps2
end

function Game.status(ps::PacoSako)::Int64
    @assert !Game.is_frozen(ps)
    if ps.forfeit_by != 0
        -ps.forfeit_by
    else
        ccall((:status, DYNLIB_PATH), Int64, (Ptr{Nothing},), ps.ptr)
    end
end

Game.current_player(ps::PacoSako)::Int64 = ccall((:current_player, DYNLIB_PATH), Int64, (Ptr{Nothing},), ps.ptr)

function Game.legal_actions(ps::PacoSako)
    @assert !Game.is_frozen(ps)
    # While there are 132 possible actions (64+64+4) there can be at most 64
    # actions that are legal at any point.
    out = zeros(UInt8, 64)
    ccall((:legal_actions, DYNLIB_PATH), Nothing, (Ptr{Nothing}, Ptr{UInt8}), ps.ptr, out)
    Int.(collect(Iterators.takewhile(x -> x > 0, out)))
end

function Game.apply_action!(ps::PacoSako, action::Int)::PacoSako
    @assert !Game.is_frozen(ps)
    status_code = ccall((:apply_action_bang, DYNLIB_PATH), Int64, (Ptr{Nothing}, UInt8), ps.ptr, UInt8(action))
    if length(Game.legal_actions(ps)) == 0 && ccall((:status, DYNLIB_PATH), Int64, (Ptr{Nothing},), ps.ptr) == 42
        ps.forfeit_by = Game.current_player(ps)
    end
    @assert status_code == 0 "Error during apply_action! of PacoSako game"
    ps
    end

function Game.array(ps::PacoSako)::Array{Float32,3}
    size = Base.size(ps)
    memory = zeros(Float32, prod(size))
    status_code = ccall((:repr, DYNLIB_PATH), Int64, (Ptr{Nothing}, Ptr{Float32}, Int64), ps.ptr, memory, length(memory))
    @assert status_code == 0 "Error while determining the game representation"
    reshape(memory, size)
end

function Base.size(:: Type{PacoSako})
    layer_count = ccall((:repr_layer_count, DYNLIB_PATH), Int64, ())
    @assert layer_count > 0 "Layer count must be positive"
    (8, 8, layer_count)
end

Game.policy_length(:: Type{PacoSako})::Int = 132

# Only when a human player wants to play
# draw(io :: IO, game :: PacoSako) :: Nothing = error("drawing $(typeof(game)) not implemented.")

# For performance:
# function is_action_legal(game :: PacoSako, action :: ActionIndex)

################################################################################
## (De-)Serialization ##########################################################
################################################################################

function serialize(ps::PacoSako)::Vector{UInt8}
    @assert !Game.is_frozen(ps)
    length = ccall((:serialize_len, DYNLIB_PATH), Int64, (Ptr{Nothing},), ps.ptr)
    out = zeros(UInt8, length)
    status_code = ccall((:serialize, DYNLIB_PATH), Int64, (Ptr{Nothing}, Ptr{UInt8}, Int64), ps.ptr, out, length)
    @assert status_code == 0 "Error during serialization of PacoSako game!"
    out
end

function deserialize(bincode::Vector{UInt8})::PacoSako
    ptr = ccall((:deserialize, DYNLIB_PATH), Ptr{Nothing}, (Ptr{UInt8}, Int64), bincode, length(bincode))
    @assert ptr != C_NULL "Deserialization error for PacoSako game!"
    ps = wrap_pacosako_ptr(ptr)
    if length(Game.legal_actions(ps)) == 0 && ccall((:status, DYNLIB_PATH), Int64, (Ptr{Nothing},), ps.ptr) == 42
        ps.forfeit_by = Game.current_player(ps)
    end
    ps
    end

function Game.is_frozen(ps::PacoSako)::Bool
    !isnothing(ps.cache)
end

function Game.freeze(ps::PacoSako)::PacoSako
    @assert !Game.is_frozen(ps)
    PacoSako(C_NULL, serialize(ps), ps.forfeit_by)
end

function Game.unfreeze(ps::PacoSako)::PacoSako
    @assert Game.is_frozen(ps)
    deserialize(ps.cache)
end

################################################################################
## Helpers #####################################################################
################################################################################

function Base.show(io::IO, game::PacoSako)
  if Game.is_over(game)
    print(io, "PacoSako($(Game.status(game)) won)")
  else
    print(io, "PacoSako($(Game.current_player(game)) moving)")
  end
end

function Base.show(io::IO, :: MIME"text/plain", game::PacoSako)
  if Game.is_over(game)
    print(io, "PacoSako game with result $(Game.status(game))")
  else
    print(io, "PacoSako game with player $(Game.current_player(game)) moving")
  end
end

function Game.draw(ps::PacoSako)
    @assert !Game.is_frozen(ps)
    ccall((:print, DYNLIB_PATH), Nothing, (Ptr{Nothing},), ps.ptr)
end

function Base.:(==)(ps1::PacoSako, ps2::PacoSako)::Bool
    ccall((:equals, DYNLIB_PATH), Int64, (Ptr{Nothing}, Ptr{Nothing}), ps1.ptr, ps2.ptr) == 0
end

function Game.hash(ps::PacoSako)::UInt64
    @assert !Game.is_frozen(ps)
    ccall((:hash, DYNLIB_PATH), UInt64, (Ptr{Nothing},), ps.ptr)
end

"""
Returns a random Paco Ŝako position that is legal and still running.
"""
function random_position()::PacoSako
    ptr = ccall((:random_position, DYNLIB_PATH), Ptr{Nothing}, ())
    @assert ptr != C_NULL "Error in the random generator for PacoSako"
    wrap_pacosako_ptr(ptr)
end

"""
Given a Paco Ŝako position, this returns a vector that contains all possible
chains for the current player to unite with the opponents king. (Only direct
chains, no "Paco in 2").

A chain has type Vector{Int64}, so we return Vector{"Chain"}.

If there are more than 30 chains or they are longer than 30 actions, these are
not returned.
"""
function find_sako_sequences(ps::PacoSako)::Vector{Vector{Int64}}
    memory = zeros(UInt8, 1000)

    status_code = ccall((:find_sako_sequences, DYNLIB_PATH), Int64,
        (Ptr{Nothing}, Ptr{UInt8}, Int64),
        ps.ptr, memory, length(memory))
    @assert status_code == 0 "Error when trying to find sequences"

    # Now we need to split this along the 0
    out = Vector()
    chain = Vector()
    for action in memory
        if action != 0
            push!(chain, action)
        elseif length(chain) > 0
            push!(out, chain)
            chain = Vector()
        end
    end
    out
end

################################################################################
## Generates states where the best policy is known. ############################
################################################################################

"""
Returns a vector of positions together with a single action that is optimal
in this situation. This may return the same position twice if there is more than
one optimal action. (i.e. two ways to capture the king.)
"""
function find_simple_positions(; tries=100)::Training.Dataset{PacoSako}
    result = Training.Dataset{PacoSako}()
    for _ in 1:tries
        ps = random_position()
        solutions = find_sako_sequences(ps)
        for chain in solutions
            ps2 = copy(ps)
            for action in chain
                push!(result.games, copy(ps2))
                label = Util.one_hot(1 + 132, 1 + action)
                label[1] = 1
                push!(result.label, label)
                push!(result.flabel, Vector())

                Game.apply_action!(ps2, action)
            end
        end
    end
    result
end

function __init__()
  # We have to register the game in order to use all functionality of Jtac
  # (loading and saving datasets and models)
  Game.register!(PacoSako)
end

################################################################################
## PacoPlay module to interact with pacoplay servers ###########################
################################################################################

module PacoPlay

  using ..JtacPacoSako
  using HTTP, LazyJSON

  include("pacoplay.jl")

end # module PacoPlay

export PacoPlay

end

max_stars_repo_name: kreibaum/pacosako

max_issues_repo_name: kreibaum/pacosako

max_forks_repo_name: kreibaum/pacosako


text:
using Test
using RealNeuralNetworks.SWCs
using RealNeuralNetworks.NodeNets
using RealNeuralNetworks.NBLASTs
using RealNeuralNetworks.Utils.VectorClouds

ASSET_DIR = joinpath(@__DIR__, "../../asset/")

NEURON_ID1 = 77641
NEURON_ID2 = 77625

@testset "test NBLAST module..." begin
    neuron1 = SWCs.load(joinpath(ASSET_DIR, "$(NEURON_ID1).swc.bin")) |> NodeNet;
    neuron2 = SWCs.load(joinpath(ASSET_DIR, "$(NEURON_ID2).swc.bin")) |> NodeNet;

    vectorCloud1 = NBLASTs.VectorCloud(neuron1)
    vectorCloud2 = NBLASTs.VectorCloud(neuron2)

    distMatrix = VectorClouds.query(vectorCloud1, vectorCloud2)
    @test any(distMatrix .!== zero(Float32))
end

ext: jl


text:
module ShaleDrillingLikelihood

# general libraries
using StatsFuns
using LinearAlgebra
using Base.Threads
using Halton
using Dates
using Calculus
using Distributions
using Test
using SparseArrays
using AxisAlgorithms
using Interpolations
using LoopVectorization
using ProgressMeter
using GenGlobal
using SharedArrays
using Distributed
using CountPlus
using Optim
using StatsBase
using ClusterManagers
using DataFrames
using UnsafeArrays

# extend these methods
import Base: length, size, iterate,
    firstindex, lastindex, eachindex, getindex, IndexStyle,
    view, ==, eltype, +, -, isless,
    fill!,string, show, convert, eltype,
    step

import StatsBase: coeftable, coefnames

export coefnames, print_in_binary_for_copy_paste

# specific functions
using Printf: @sprintf
# Broken. Need to check out
# https://github.com/JuliaStats/Distributions.jl/pull/691
# https://github.com/JuliaStats/Distributions.jl/pull/1058
using Distributions: _tnmom1
using StatsBase: countmap, sample
using Base.Iterators: flatten, product, OneTo
using Dates: Month
using LinearAlgebra: checksquare, stride1
using Optim: minimizer

using IterativeSolvers
# using IncompleteLU: ilu
# using Preconditioners: DiagonalPreconditioner, UpdatePreconditioner!

using InteractiveUtils: subtypes # showtypetree in test

# Real arrays
const AbstractRealArray{T,N} = AbstractArray{T,N} where {T<:Real,N}
const AbstractArray3{T} = AbstractArray{T,3}
const AbstractArray4{T} = AbstractArray{T,4}
const AbstractArray5{T} = AbstractArray{T,5}

abstract type AbstractTmpVars end

# models
#---------------------

export AbstractModel,
    NoModel,
    AbstractDrillModel, AbstractDynamicDrillModel, AbstractStaticDrillModel,
    AbstractProductionModel,
    AbstractRoyaltyModel,
    _nparm,
    _model,
    sprintf_binary,
    AbstractPayoffFunction,
    AbstractStaticPayoff,
    AbstractPayoffComponent,
    AbstractDrillingRevenue,
    AbstractDrillingCost,
    AbstractExtensionCost,
    AbstractScrapValue

# for modeling
abstract type AbstractModel end

"No model"
struct NoModel <: AbstractModel end
length(::NoModel) = 0
_nparm(::NoModel) = 0

abstract type AbstractProductionModel    <: AbstractModel end
abstract type AbstractRoyaltyModel       <: AbstractModel end
abstract type AbstractDrillModel         <: AbstractModel end
abstract type AbstractDynamicDrillModel  <: AbstractDrillModel end
abstract type AbstractStaticDrillModel   <: AbstractDrillModel end

abstract type AbstractModelVariations end

# Static Payoff
abstract type AbstractPayoffFunction end
abstract type AbstractStaticPayoff   <: AbstractPayoffFunction end
abstract type AbstractPayoffComponent <: AbstractPayoffFunction end

# payoff components
abstract type AbstractDrillingRevenue <: AbstractPayoffComponent end
abstract type AbstractDrillingCost    <: AbstractPayoffComponent end
abstract type AbstractExtensionCost   <: AbstractPayoffComponent end
abstract type AbstractScrapValue      <: AbstractPayoffComponent end

# also needed
abstract type AbstractStateSpace end
abstract type AbstractUnitProblem <: AbstractStateSpace end

# data structures
#---------------------

# For data structures

export AbstractDataDrill

# "Collection of data on a particular outcome for individuals `i`"
# "What we feed into a likelihood"
# "Group of observations"
abstract type AbstractDataStructure end
abstract type AbstractDataSetofSets    <: AbstractDataStructure end

abstract type AbstractDataSet          <: AbstractDataStructure end
abstract type AbstractObservationGroup <: AbstractDataStructure end
abstract type AbstractObservation      <: AbstractDataStructure end

abstract type AbstractDataDrill <: AbstractDataSet end

const DataOrObs = Union{AbstractDataSet,AbstractObservation}

_model(x::AbstractDataStructure) = x.model

export EmptyDataSet

"Empty Data Set"
struct EmptyDataSet <: AbstractDataSet end
length(d::EmptyDataSet) = 0
eachindex(d::EmptyDataSet) = 1:typemax(Int)
_nparm(d::EmptyDataSet) = 0
_model(d::EmptyDataSet) = NoModel()
coefnames(d::EmptyDataSet) = Vector{String}(undef,0)

# price / cost  / year
#----------------------------

# zchars
second(z::Tuple) = getindex(z,2)
logprice(  z::NTuple{N,Real}) where {N} = first(z)
logrigrate(z::NTuple{N,Real}) where {N} = second(z)
year(      z::NTuple{N,Real}) where {N} = last(z)

# useful functions
#----------------------------

# to get a scalar one or zero
aone(x) = one(eltype(x))
azero(x) = zero(eltype(x))

peturb(x::T) where {T<:Real} = max( abs(x), one(T) ) * cbrt(eps(T))

function showtypetree(T, level=0)
    println("\t" ^ level, T)
    for t in subtypes(T)
        showtypetree(t, level+1)
   end
end

function sprintf_binary(x::Vector{<:Number})
    xstr = reduce(*, @sprintf("%a, ", i) for i in x)
    return "[" * xstr * "]"
end
@deprecate print_in_binary_for_copy_paste(x) sprintf_binary(x)

check_finite(x::AbstractArray) = all(isfinite.(x)) || throw(error("x not finite!"))
check_finite(x::AbstractVector) = all(isfinite.(x)) || throw(error("x not finite! $x"))
check_finite(x::Number) = isfinite(x) || throw(error("x not finite! $x"))

all_same_value(x) = all(x .== first(x))
range_i_to_ip1(x,i) = x[i] : (x[i+1]-1)

# Overall structure
#----------------------------

include("utilities/threadutils.jl")
include("utilities/sum-functions.jl")
include("utilities/inplace-interpolation.jl")
include("utilities/delegate-methods.jl")
include("utilities/helper-macros.jl")

include("time-variables/tvpack.jl")
include("time-variables/tauchen.jl")
include("time-variables/time-variable-type.jl")
include("time-variables/time-series-processes.jl")

# data structures
include("data/observation-group.jl")
include("data/simulation-draws.jl")
include("data/royalty.jl")
include("data/production.jl")

include("data/drilling-data-tmpvars.jl")
include("data/drilling.jl")

include("data/overall.jl")

# drilling model
# ------------------------------------
include("drilling-model/abstract.jl")
include("drilling-model/test-reward-and-model.jl")
include("drilling-model/state-space.jl")

# reward function and components
include("drilling-model/drilling-reward.jl")
include("drilling-model/extend-and-scrap.jl")
include("drilling-model/cost.jl")
include("drilling-model/revenue.jl")

# dynamic model
include("drilling-model/dynamic-drilling-tmpvars.jl")
include("drilling-model/value-function.jl")
include("drilling-model/dynamic-drilling-model.jl")

# VF iteration components
include("drilling-model/dcdp-components/makeIminusTVp.jl")
include("drilling-model/dcdp-components/learning_transition.jl")
include("drilling-model/dcdp-components/vfit.jl")
include("drilling-model/dcdp-components/solve-all-vfit.jl")

# simulation
include("drilling-model/data-simulation.jl")

# Likelihood / solution
# ------------------------------------

# likelihoods
include("likelihood/royalty.jl")
include("likelihood/production.jl")
include("likelihood/drilling.jl")
include("likelihood/overall.jl")

# solution
include("likelihood/nfxp.jl")
include("likelihood/optimize.jl")
include("likelihood/display-results.jl")

# parameters, model generation
include("SDLParameters/SDLParameters.jl")

# counterfactuals
include("counterfactuals/shared-simulations.jl")
include("counterfactuals/objects.jl")
include("counterfactuals/sparse-state-transition.jl")
include("counterfactuals/simulate-lease.jl")
include("counterfactuals/simulate-unit.jl")
include("counterfactuals/wrapper.jl")

include("likelihood/posteriors.jl")

include("precompile.jl")
__precompile__()

end # module


text:
# Classic Hodgkin Huxley neuron with a "current pulse" stimulus
using OrdinaryDiffEq, Plots
using Conductor, IfElse, Unitful, ModelingToolkit
import Unitful: mV, mS, cm, µm, pA, nA, mA, µA, ms
import Conductor: Na, K # shorter aliases for Sodium/Potassium

Vₘ = MembranePotential()

nav_kinetics = [
    Gate(AlphaBetaRates,
         αₘ = IfElse.ifelse(Vₘ == -40.0, 1.0, (0.1*(Vₘ + 40.0))/(1.0 - exp(-(Vₘ + 40.0)/10.0))),
         βₘ = 4.0*exp(-(Vₘ + 65.0)/18.0),
         p = 3)
    Gate(AlphaBetaRates,
         αₕ = 0.07*exp(-(Vₘ+65.0)/20.0),
         βₕ = 1.0/(1.0 + exp(-(Vₘ + 35.0)/10.0)))]

kdr_kinetics = [
    Gate(AlphaBetaRates,
         αₙ = IfElse.ifelse(Vₘ == -55.0, 0.1, (0.01*(Vₘ + 55.0))/(1.0 - exp(-(Vₘ + 55.0)/10.0))),
         βₙ = 0.125 * exp(-(Vₘ + 65.0)/80.0),
         p = 4)]

@named NaV = IonChannel(Sodium, nav_kinetics, 120mS/cm^2)
@named Kdr = IonChannel(Potassium, kdr_kinetics, 36mS/cm^2)
@named leak = PassiveChannel(Leak, 0.3mS/cm^2)

# Equilibrium potentials are a implicit description of a ion concentration gradient
gradients = Equilibria([Na   =>  50.0mV,
                        K    => -77.0mV,
                        Leak => -54.4mV])

area = 4*pi*(20µm)^2
pulse(t, current) = 100. < t < 200. ? ustrip(Float64, µA, 400pA) : 0.0
@register pulse(a,b)

@named neuron = Soma([NaV,Kdr,leak], gradients, stimulus = pulse, area = ustrip(Float64, cm^2, area));

t = 300
sim = Simulation(neuron, time = t*ms)
solution = solve(sim, Rosenbrock23())

# Plot at 5kHz sampling
plot(solution; plotdensity=Int(t*5), size=(1200,800))


text:
#!/Applications/Julia-0.4.6.app/Contents/Resources/julia/bin/julia
# Mortgage Calculator
# This calculator works in any decimal-based currency.

module Mortgage

export mortgage, mortgagecalc, printsummary, printtable

include("mortgageParameters.jl") # uses dictionaries to expand on input arguments
include("mortgageFunctions.jl")
include("mortgagePrintouts.jl")

using DateParser

"""
    mortgage(<keyword arguments>)

    (principal, rate, amortization, frequency, compounding, startdate, termString, paymentSize, firstPaymentDate, numberOfPayments, accumulatedPrincipal, accumulatedInterest, accumulatedTotal, balance, finalPayment, finalPaymentDate, table) = mortgage(principal, rate, amortization, frequency, compounding, startdate, term, payment)

Return calculated values for mortgages or other loans.

# Arguments
* `principal::Number`: the principal amount of the loan or mortgage, in any decimal-based currency. Default: principal=100000
* `rate::Number`: annual interest rate, in percent, eg 3.26 . Default: rate=10.0
* `amortization::Number`: the number of years over which the entire loan or mortgage would be paid off. Default is amortization=25
* `frequency::String`: "m" for monthly (default); "w" for weekly; "t" for two weeks; "b" for bimonthly. Note that for bimonthly payments, they will occur on the first and the fifteenth of each month, and the mortgage should start on the first or fifteenth of the month.
* `compounding::String`: "s" for none (simple interest; note that interest accrues daily but is not compounded); "m" for monthly (ie American) (this is the default); "c" for Canadian (ie semi-annual. Note that variable rate mortgages often compound monthly - check the fine print.)
* `startdate::String`: start date for the mortgage; default is today's date.
* `term::String`: specify the term in years; use "1/4" for 3 months and "1/2" for 6 months; enter "a" to indicate for the entire amortization interval (ie until paid off); default is 5 years. A term greater than the amortization will generate an error.
* `payment::Number`: payment amount; if not specified, it will be calculated based on the amortization interval. Note that for simple interest mortgages, the payment will be calculated as for monthly compounded mortgages.

# table
This value returned by mortgage() is a one-dimensional array with eight values for each payment. The values are:
	paymentNumber, paymentDate, principalAmount, interestAmount, accumulatedPrincipal, accumulatedInterest, accumulatedTotal, balance.
These values are used by printtable() to print out a listing with one line for each payment.

# Examples
```
julia> mortgage(principal=54000, rate=2.125, amortization=20, frequency="w", compounding="c", startdate="2016-6-29", term="a")

(54000,2.125,20,"w","c",2016-06-29,"until paid off",63.50799378958494,2016-07-06,1044,54000.00000000001,12229.766528153477,66229.76652815354,0,54.43699940601391,2036-06-25,Any[1,2016-07-06,41.61279659644556,21.89519719313937,41.61279659644556,21.89519719313937,63.50799378958494,53958.38720340355,2,2016-07-13  …  66175.32952874753,54.41493596613927,1043,2036-06-25,63.485930349710294,0.022063439874642057,54009.070994383575,12229.766528153477,66238.83752253711,-9.070994383571026])
```
```
julia> printsummary(mortgage(startdate="2016-6-28")...)

Principal: 100000; Annual Interest Rate: 10.0%; Payment frequency: monthly
Compounding: monthly (American) compounding
Your mortgage starts on 2016-06-28 and is amortized over (ie would be fully paid off in) 25.0 years.
Your first payment of 908.70 will be on 2016-07-29.
During the term of 5 years, you will make 60 payments, with a final payment of 908.70 on 2021-06-28.
At the end of the term, the balance remaining will be 94163.77. You will have paid a total of 54522.04
of which 48685.81, or 89.3%, will be interest. This represents 48.7% of the principal amount.
```
```
julia> printtable(mortgage(startdate="2016-6-29", term="1/4")...)

                       Mortgage Schedule of Payments

Mortgage Principal: 100000.00 at 10.00% annual interest, amortized over 25.0 years,
using monthly (American) compounding, to be repaid with 3 payments of 908.70 each,
for a term of 3 months. The mortgage start date is 2016-06-29.

                                                   Accumulated   Accumulated   Accumulated
Payment         Date    Principal     Interest       Principal      Interest         Total         Balance

      1   2016-07-30        75.37       833.33           75.37        833.33        908.70        99924.63
      2   2016-08-30        76.00       832.71          151.36       1666.04       1817.40        99848.64
      3   2016-09-29        76.63       832.07          227.99       2498.11       2726.10        99772.01

At the end of the term, the outstanding balance will be 99772.01.
The last payment of the term will be on 2016-09-29 in the amount of 908.70.
Over the term, you will have paid a total of 2726.10 of which 2498.11, or 91.64%, is interest. This
represents 2.50% of the principal amount.
```

# Usage
Commonly used with printsummary() or printtable(), which are part of this package.
"""
function mortgage(; principal=100000, rate=10.0, amortization=25, frequency="m", compounding="m", startdate=today(), term="5", payment=nothing)
	@show typeof(startdate)
	if typeof(startdate) == AbstractString
		startdate = get(tryparse(Date, startdate))
	end
	# @show startdate
	return mortgagecalc(principal, rate, amortization, frequency, compounding, startdate, term, payment)
end

function mortgagecalc(principal, rate, amortization, frequency, compounding, startdate, term, payment)
	# obtain the length of the term in years
	termLength = termlength(term, amortization)
	# string suitable for printing
	termString = haskey(mortgageTermDescriptors, term) ? mortgageTermDescriptors[term][1] : "$(term) years"
	firstPaymentDate = nextpaymentdate(startdate, frequency, startdate)
	# how many payments will be made over the term of the mortgage
	numberOfPayments = numberofperiods(frequency, termLength, startdate)
	if payment == nothing # if payment size was not specified, calculate it based on amortization and other parameters
		paymentSize = paymentsizecalc(rate, principal, amortization, compounding, frequency, startdate)
	else
		paymentSize = payment
	end
	accumulatedPrincipal, accumulatedInterest, accumulatedTotal, balance, finalPayment, finalPaymentDate, table = dotablerows(principal, rate, frequency, compounding, startdate, firstPaymentDate, paymentSize, numberOfPayments)
	return principal, rate, amortization, frequency, compounding, startdate, termString, paymentSize, firstPaymentDate, numberOfPayments, accumulatedPrincipal, accumulatedInterest, accumulatedTotal, balance, finalPayment, finalPaymentDate, table
end

function main()
	printsummary(mortgage()...)
	printtable(mortgage()...)
end

# uncomment the line below, to run this module from the command line. However, it is preferable
# to use the mortgagecl.jl when one wants to use the command line.
# main()

end # module


text:
using VisJS
using LightGraphs

main(window) = begin
    push!(window.assets, ("VisJS", "vis-plot"))
    VisJS.drawGraph(WheelGraph(10))
end


text:
function optimize(tuning_run::Run)
    stopping_criterion  = @task tuning_run.stopping_criterion(tuning_run.duration)
    reporting_criterion = @task tuning_run.reporting_criterion(tuning_run.report_after)
    stop                = consume(stopping_criterion)
    results             = initialize_search_tasks!(tuning_run)
    best                = get_new_best(results)
    iteration           = 1
    start_time          = time()
    produce(best)
    while !stop
        best                    = get_new_best(results, best)
        iteration              += 1
        best.current_iteration  = iteration
        stop                    = consume(stopping_criterion)
        if stop
            best.is_final     = true
            best.current_time = time() - start_time
            produce(best)
        elseif consume(reporting_criterion)
            best.current_time = time() - start_time
            produce(best)
        end
    end
end


text:
using Test

include("./consec-primes-sum.jl")

@testset "prime sum ≤ 100" begin
  @time (sum, ary, nterms) = consecutive_prime_sum(100)
  @test (sum, ary[1], ary[end], nterms) == (41, 2, 13, 6)
end

@testset "prime sum ≤ 1000" begin
  @time (sum, ary, nterms) = consecutive_prime_sum(1000)
  @test (sum, ary[1], ary[end], nterms) == (953, 7, 89, 21)
end

@testset "prime sum ≤ 10_000" begin
  @time (sum, ary, nterms) = consecutive_prime_sum(10_000)
  @test (sum, ary[1], ary[end], nterms) == (9521, 3, 317, 65)
end

@testset "prime sum ≤ 100_000" begin
  @time (sum, ary, nterms) = consecutive_prime_sum(100_000)
  @test (sum, ary[1], ary[end], nterms) == (92951, 3, 1097, 183)
end

@testset "prime sum ≤ 1_000_000" begin
  @time (sum, ary, nterms) = consecutive_prime_sum(1_000_000)
  @test (sum, ary[1], ary[end], nterms) == (997651, 7, 3931, 543)
end

@testset "prime sum ≤ 10_000_000" begin
  @time (sum, ary, nterms) = consecutive_prime_sum(10_000_000)
  @test (sum, ary[1], ary[end], nterms) == (9951191, 5, 13399, 1587)
end

@testset "prime sum ≤ 100_000_000" begin
  @time (sum, ary, nterms) = consecutive_prime_sum(100_000_000)
  @test (sum, ary[1], ary[end], nterms) == (99819619, 7, 45161, 4685)
end

@testset "prime sum ≤ 1_000_000_000" begin
  @time (sum, ary, nterms) = consecutive_prime_sum(1_000_000_000)
  @test (sum, ary[1], ary[end], nterms) == (999715711, 11, 151051, 13935)
end

@testset "prime sum ≤ 10_000_000_000" begin
  @time (sum, ary, nterms) = consecutive_prime_sum(10_000_000_000)
  @test (sum, ary[1], ary[end], nterms) == (9999419621, 2, 502237, 41708)
end

@testset "prime sum ≤ 100_000_000_000" begin
  @time (sum, ary, nterms) = consecutive_prime_sum(100_000_000_000)
  @test (sum, ary[1], ary[end], nterms) == (99987684473, 19, 1662257, 125479)
end

@testset "prime sum ≤ 1_000_000_000_000" begin
  @time (sum, ary, nterms) = consecutive_prime_sum(1_000_000_000_000)
  @test (sum, ary[1], ary[end], nterms) == (999973156643, 5, 5476973, 379317)
end

@testset "prime sum ≤ 1_000_000_000_000_000" begin
  @time (sum, ary, nterms) = consecutive_prime_sum(1_000_000_000_000_000)
  @test (sum, ary[1], ary[end], nterms) == (999998764608469, 7, 192682309, 10695879)
end

## Too inefficient...

# @testset "alt prime sum ≤ 100" begin
#   @time (sum, ary, nterms) = consecutive_prime_sum_alt(100)
#   @test (sum, ary[1], ary[end], nterms) == (41, 2, 13, 6)
# end

# @testset "alt prime sum ≤ 1000" begin
#   @time (sum, ary, nterms) = consecutive_prime_sum_alt(1000)
#   @test (sum, ary[1], ary[end], nterms) == (953, 7, 89, 21)
# end

# @testset "alt prime sum ≤ 10_000" begin
#   @time (sum, ary, nterms) = consecutive_prime_sum_alt(10_000)
#   @test (sum, ary[1], ary[end], nterms) == (9521, 3, 317, 65)
# end

# @testset "alt prime sum ≤ 100_000" begin
#   @time (sum, ary, nterms) = consecutive_prime_sum_alt(100_000)
#   @test (sum, ary[1], ary[end], nterms) == (92951, 3, 1097, 183)
# end

# @testset "alt prime sum ≤ 1_000_000" begin
#   @time (sum, ary, nterms) = consecutive_prime_sum_alt(1_000_000)
#   @test (sum, ary[1], ary[end], nterms) == (997651, 7, 3931, 543)
# end

# @testset "alt prime sum ≤ 10_000_000" begin
#   @time (sum, ary, nterms) = consecutive_prime_sum_alt(10_000_000)
#   @test (sum, ary[1], ary[end], nterms) == (9951191, 5, 13399, 1587)
# end

# @testset "alt prime sum ≤ 100_000_000" begin
#   @time (sum, ary, nterms) = consecutive_prime_sum_alt(100_000_000)
#   @test (sum, ary[1], ary[end], nterms) == (99819619, 7, 45161, 4685)
# end

# @testset "alt prime sum ≤ 1_000_000_000" begin
#   @time (sum, ary, nterms) = consecutive_prime_sum_alt(1_000_000_000)
#   @test (sum, ary[1], ary[end], nterms) == (999715711, 11, 151051, 13935)
# end

# @testset "alt prime sum ≤ 10_000_000_000" begin
#   @time (sum, ary, nterms) = consecutive_prime_sum_alt(10_000_000_000)
#   @test (sum, ary[1], ary[end], nterms) == (9999419621, 2, 502237, 41708)
# end

# @testset "alt prime sum ≤ 100_000_000_000" begin
#   @time (sum, ary, nterms) = consecutive_prime_sum_alt(100_000_000_000)
#   @test (sum, ary[1], ary[end], nterms) == (99987684473, 19, 1662257, 125479)
# end

# @testset "alt prime sum ≤ 1_000_000_000_000" begin
#   @time (sum, ary, nterms) = consecutive_prime_sum_alt(1_000_000_000_000)
#   @test (sum, ary[1], ary[end], nterms) == (999973156643, 5, 5476973, 379317)
# end

max_stars_repo_name: pascal-p/Euler

max_issues_repo_name: pascal-p/Euler

max_forks_repo_name: pascal-p/Euler


text:
# This file is a part of TextSearch.jl

export tokenize, tokenize_corpus, qgrams, unigrams, encode, decode

const EXTRA_PUNCT = Set(['~', '+', '^', '$', '|', '<', '>'])

"""
    tokenize_corpus(textconfig::TextConfig, arr; minbatch=0)

Tokenize a list of texts.
"""
function tokenize_corpus(textconfig::TextConfig, arr; minbatch=0)
    n = length(arr)
    L = Vector{Vector{String}}(undef, n)
    minbatch = getminbatch(minbatch, n)

    # @batch minbatch=minbatch per=thread
    Threads.@threads for i in 1:n
        buff = take!(CACHES)
        empty!(buff)
        try
            L[i] = copy(tokenize(textconfig, arr[i]))
        finally
            put!(CACHES, buff)
        end
    end

    L
end

"""
    tokenize(textconfig::TextConfig, text::AbstractString, buff=TextSearchBuffer())

Tokenizes `text` using the given configuration
"""
function tokenize(textconfig::TextConfig, text::AbstractString, buff=TextSearchBuffer())
    normalize_text(textconfig, text, buff.normtext)
    tokenize_(textconfig, buff)
end

function tokenize_(config::TextConfig, buff::TextSearchBuffer)
    for q in config.qlist
        qgrams(q, buff)
    end

    if length(config.nlist) > 0 || length(config.slist) > 0
        n1 = length(buff.tokens)
        unigrams(buff)  # unigrams are always activated if any |nlist| > 0 or |slist| > 0

        if length(config.nlist) == 0 || config.nlist[1] != 1 # always sorted
            resize!(buff.tokens, n1)
        end

        for q in config.nlist
            q != 1 && nwords(q, buff)
        end

        for q in config.slist
            skipgrams(q, buff)
        end
    end

    buff.tokens
end

"""
    flush_token!(buff::TextSearchBuffer)

Pushes the word inside the buffer to the token list; it discards empty strings.
"""
function flush_token!(buff::TextSearchBuffer)
    io = buff.io
    if io.size > 0
        s = String(take!(io))
        push!(buff.tokens, s)
        s
    else
        nothing
    end
end

"""
    qgrams(q::Integer, buff::TextSearchBuffer)

Computes character q-grams for the given input
"""
function qgrams(q::Integer, buff::TextSearchBuffer)
    n = length(buff.normtext)

    for i in 1:(n - q + 1)
        write(buff.io, '\t', 'q')
        for j in i:i+q-1
            @inbounds write(buff.io, buff.normtext[j])
        end
        flush_token!(buff)
    end

    buff.tokens
end

ispunct2(c) = ispunct(c) || c in EXTRA_PUNCT

"""
    unigrams(buff::TextSearchBuffer)

Performs the word tokenization
"""
function unigrams(buff::TextSearchBuffer)
    n = length(buff.normtext)
    # @info buff.normtext
    @inbounds for i in 2:n  # normtext[1] is BLANK
        c = buff.normtext[i]
        p = buff.normtext[i-1]

        ## @show i, p, c
        if ispunct2(c) && !ispunct2(p) && p !== BLANK
            ## @show :a
            s = flush_token!(buff)
            s !== nothing && push!(buff.unigrams, s)
            write(buff.io, c)
        elseif ispunct2(p)
            if ispunct2(c) && buff.io.size > 2
                s = flush_token!(buff)
                s !== nothing && push!(buff.unigrams, s)
                write(buff.io, c)
            elseif !ispunct2(c) && !(p in ('#', '@', '_'))
                ## @show :b
                s = flush_token!(buff)
                s !== nothing && push!(buff.unigrams, s)
                c !== BLANK && write(buff.io, c)
            else
                write(buff.io, c)
            end
        elseif isemoji(c)
            s = flush_token!(buff)
            s !== nothing && push!(buff.unigrams, s)
            write(buff.io, c)
            s = flush_token!(buff)
            s !== nothing && push!(buff.unigrams, s)
        elseif c == BLANK
            if p !== BLANK
                s = flush_token!(buff)
                #write(buff.io, c)
                s !== nothing && push!(buff.unigrams, s)
            end
        else
            ## @show :d
            write(buff.io, c)
        end
    end

    s = flush_token!(buff)
    s !== nothing && push!(buff.unigrams, s)
    buff.tokens
end

"""
    nwords(q::Integer, buff::TextSearchBuffer)
"""
function nwords(q::Integer, buff::TextSearchBuffer)
    n = length(buff.unigrams)

    @inbounds for i in 1:(n - q + 1)
        _last = i + q - 1
        write(buff.io, '\t', 'n')
        for j in i:_last-1
            write(buff.io, buff.unigrams[j])
            write(buff.io, BLANK)
        end

        write(buff.io, buff.unigrams[_last])
        flush_token!(buff)
    end

    buff.tokens
end

"""
    skipgrams(q::Skipgram, buff::TextSearchBuffer)

Tokenizes using skipgrams
"""
function skipgrams(q::Skipgram, buff::TextSearchBuffer)
    n = length(buff.unigrams)

    for start in 1:(n - (q.qsize + (q.qsize - 1) * q.skip) + 1)
        write(buff.io, '\t', 's')
        if q.qsize == 2
            write(buff.io, buff.unigrams[start])
            write(buff.io, BLANK)
            write(buff.io, buff.unigrams[start + 1 + q.skip])
        else
            ep = q.qsize - 2
            for i in 0:ep
                write(buff.io, buff.unigrams[start + i * (1+q.skip)])
                write(buff.io, BLANK)
            end
            ep += 1
            write(buff.io, buff.unigrams[start + ep * (1+q.skip)])
        end

        flush_token!(buff)
    end

    buff.tokens
end

max_stars_repo_name: sadit/TextModel

max_issues_repo_name: sadit/TextModel

max_forks_repo_name: sadit/TextModel


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

using Markdown
using InteractiveUtils

# ╔═╡ 5000b8f3-8a09-4440-80e9-ab56325de90f
begin
using DataFrames
using Plots
end

# ╔═╡ 266c7f54-ce35-4b97-bdb6-bb5611332811
md"""
# Multi-objective optimization in RNA-seq deconvolution.

Multi-objective optimization is used to solve problems that require more than one objective function to be optimized simultaneously. Typically, there is not one single solution that optimizes each objective.
"""

# ╔═╡ d6285877-636a-4804-8790-7e4525d870b9
md"""
## Easy example

Consider two towns, with two paths between them. The objectives that we care about are the distance (km) between the towns, and the travel time (h).

Both paths are 1000 km long, so path A and path B are equally good. Each path has a 50% chance of being choosen.

![]
(https://github.com/licollier/Multiobjectopt/blob/master/notebook/Figures/1000 km.jpg?raw=true)
"""

# ╔═╡ c6af78f8-d0f2-48ed-b607-7c09dd3d535d
md"""

Now, let's imagine that the first path has a speed limit of 50 km/h and the second path one of 100 km/h. If we would always drive at this speed limit, it would take us about 20 hours to reach the other city. If we would take the second path, this would take us only 10 hours. Based on the travel time alone, the second path is 2 times as good as the first path. The red path has a 33% chance of being choosen, while the green path has a 66% chance of being choosen.

![]
(https://github.com/licollier/Multiobjectopt/blob/master/notebook/Figures/speedlimits.jpg?raw=true)

"""

# ╔═╡ 7cb56496-5184-44ad-9323-db908a8253c8
md"""

If we take both the distance and travel time into account, we can clearly see that the green path is better. But how much better?

If we would take a naive approach, we could just combine the distance and travel time to compute the fitness of each path.

$$red: 1000 + 20 = 1020$$
$$green: 1000 + 10 = 1010$$

The red path now has a 50,2% chance of being chosen and the green path 49,8%. The travel time has almost no impact on the fitness of the path. We could solve this by multiplying the time distance with some factor, so it becomes similar in scale to the distance:

$$red: 1000 + 20*50 = 2000$$
$$green: 1000 +10*50 = 1500$$

Now the red path has a 57% chance of being chosen, and the green path a 43% chance.
This is slightly better, but when we put time on the same scale as the distance, we assume that travel time and distance are equally important.

"""

# ╔═╡ f398de0e-f8e6-4f0f-931e-aa015d2aeb7e
md"""
By scaling one objective and just combining them to calculate the fitness of each path, we also loose information about the solutions. Look at the following example:

![]
(https://github.com/licollier/Multiobjectopt/blob/master/notebook/Figures/speedlimits2.jpg?raw=true)
"""

# ╔═╡ 4265b668-3c60-4859-98e6-71e65e8dccd8
md"""

$$red: 1000 + 10 *50 = 1500$$
$$green: 500 + 20*50 = 1500$$

Now, the red and green path have the same fitness, even tough they are very different solutions.

We have realized that just combining the travel time and distance to find the fitness of each solution is not the best way. This way we assume that each objective is equally important and we loose valuable information about the solution. So, what can we do? """

# ╔═╡ 66d7232f-c7b7-4385-95b8-460b0e570105
md"""
## Pareto fronts"""

# ╔═╡ 4bc3066e-a0f5-4829-9c72-fa9cb6046427
md"""

Continuing our problem of travelling between two towns. We now have 4 different solutions. We can visualise each solution on a simple plot. """

# ╔═╡ af094e89-71e5-4468-93a9-941a1c32f8ff
DataFrame(Distance =[1000, 750, 800, 500], Time = [10, 14, 14.5, 20])

# ╔═╡ 8147f6ce-16ac-4085-a5d5-ef3c863d1018
begin

	Distance =[1000 750 800 500 ]
	Time = [10 14 14.5 20]
	markercolor = [:red :blue :purple :green]

plot(Time,Distance,seriestype = :scatter, color = markercolor, markersize = 10,xlabel="Time (h)",ylabel="Distance (km)",legend = false)
end

# ╔═╡ 4c7e1677-bd51-475d-b996-1a3bf2d31ae2
md"""
When we compare the blue solution with the red solution, we see that blue is better in distance, but not in time. When we compare blue with green, we see that blue is better in time, but not in distance. Blue is another equally good solution as green and red, but with other trade offs between our objectives.

When we look at the purple solution, we see that blue is better both in distance and in time. We can say that purple is **dominated** by blue.

We have now found a way to order our solutions by fitness, when we have more than one objective. By identifying the dominating solutions, we can find the best solutions in our population. But what about the remainder of the solutions? Let us look at a few more solutions."""

# ╔═╡ 24785674-8024-4d9e-9bb3-8b5e4589e7b5
begin
	Distance1 =[800 700 650 600 570 525 1000 900 750 1000 850 700 850]
	Time1 = [10 11 13 15 15.5 19 11 12 14 16 13.5 16 17]

plot(Time1,Distance1,seriestype = :scatter, markersize =8,xlabel="Time (h)", ylabel="Distance (km)",legend=false)
end

# ╔═╡ 52aaf73e-7d97-43e6-810d-f3a8eea2e081
md"""

We can immediately identify the non-dominated solutions (in red), for these solutions we can not necessarily find a better solution, while for the blue ones we can.
"""

# ╔═╡ d84017c8-3e45-495d-8748-e758cca32932
begin
markercolor2=[:red :red :red :red :red :red :blue :blue :blue :blue :blue :blue :blue]
plot(Time1,Distance1,seriestype = :scatter, markersize =8,xlabel="Time (h)", ylabel="Distance (km)",legend=false,color=markercolor2)
end

# ╔═╡ aca14538-cc05-49bd-9371-f4358e70150e
md"""
The line that is formed between these non-dominated points, is called a Pareto front. Every solution on the pareto front is equally fit. Once we have the first front we can identify a second, third,fourth,... front:"""

# ╔═╡ 78bb0c77-8722-4854-aa74-d502525469c5
begin
markercolor3=[:red :red :red :red :red :red :green :green :green :yellow :green :green :yellow]
plot(Time1,Distance1,seriestype = :scatter, markersize =8,xlabel="Time (h)", ylabel="Distance (km)",legend=false,color=markercolor3)
end

# ╔═╡ 92652f0b-8112-4ed9-9412-ed714e66b2f8
md"""

We have found the red solutions to be the best, we can choose one solution on this Pareto front based on our own preferences. For example, I would rather drive more kilometers on a highway at a higher speed, than less kilometers on a "boerewegel" at low speed. So I would probably choose one of the most left solutions. """

# ╔═╡ 9350e66f-bfa0-4772-a8c9-8d42df4c76ed
md"""

Now that we understand the basic concept of multi-object optimization, how can this be used to deconvolute bulk RNA-seq data? """

# ╔═╡ ad3efd53-7051-4007-a276-b1b91aa76339
md"""
## Deconvolution"""

# ╔═╡ f8b45b20-1a32-49c1-ad84-26e165328614
md"""

Deconvolution is typically used to obtain cell fractions (composition deconvolution) from heterogenous bulk gene expression data such as blood samples or tumor samples.

A general pipeline for deconvolution can be seen below. Tumor or blood samples can be sequenced to generate a bulk RNA gene expression profile. To determine the abundance of each cell type that is present in this cell mixture, deconvolution is used. For each cell type, the gene expression profile is established, preferably by single cell RNA sequencing (scRNA-seq). These gene expression profiles can then be used to generate a signature matrix. By combining these two inputs, the cell proportions can be determined.

![]
(https://github.com/licollier/Multiobjectopt/blob/master/notebook/Figures/Deconvolution_pipeline.jpg?raw=true)"""

# ╔═╡ a7c46cef-e37d-41ee-acfa-234c527906cf
md"""

The signature matrix contains a gene expression profile for each cell type that is present in the bulk mixture. These expression profiles contain marker genes and there expression values. However, some cell types are closely related, so finding a signature profile that is unique enough to seperate them can be difficult. This is where multi-objective optimization can be used. We want to select a set of genes with two objectives: simultaneously minimize the correlation and maximize the distance between the cell types. First the Pareto optimals are found, and then it is again up to the researchers to choose what they find most important. Aliee and Theis (2021) found that using the solution with the least correlation will be the best. However, other solutions will still work well. """

# ╔═╡ 23a2aa94-aee7-44d3-9658-d41724081b0a
md"""

## References

Multiobjective Optimization | NEOS. (z.d.). Neos-Guide.Org. Geraadpleegd op 30 januari 2022, van https://neos-guide.org/content/multiobjective-optimizationTutorials with Gary. (2020, 13 juni).

Multi-Objective Optimisation - Writing your own Genetic Algorithm Part 6 [Video]. YouTube. https://www.youtube.com/watch?v=3JrpyuSHEWQ&t=569sWikipedia contributors. (2021, 26 november).

Pareto front. Wikipedia. Geraadpleegd op 30 januari 2022, van https://en.wikipedia.org/wiki/Pareto_front"""

# ╔═╡ 00000000-0000-0000-0000-000000000001
PLUTO_PROJECT_TOML_CONTENTS = """
[deps]
DataFrames = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0"
Plots = "91a5bcdd-55d7-5caf-9e0b-520d859cae80"

[compat]
DataFrames = "~1.3.2"
Plots = "~1.25.7"
"""

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

[[Adapt]]
deps = ["LinearAlgebra"]
git-tree-sha1 = "af92965fb30777147966f58acb05da51c5616b5f"
uuid = "79e6a3ab-5dfb-504d-930d-738a2a938a0e"
version = "3.3.3"

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

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

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

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

[[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 = "4b859a208b2397a7a623a03449e4636bdb17bcf2"
uuid = "83423d85-b0ee-5818-9007-b63ccbeb887a"
version = "1.16.1+1"

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

[[ChangesOfVariables]]
deps = ["ChainRulesCore", "LinearAlgebra", "Test"]
git-tree-sha1 = "bf98fa45a0a4cee295de98d4c1462be26345b9a1"
uuid = "9e997f8a-9a97-42d5-a9f1-ce6bfc15e2c0"
version = "0.1.2"

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

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

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

[[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 = "44c37b4636bc54afac5c574d2d02b625349d6582"
uuid = "34da2185-b29b-5c13-b0c7-acf172513d20"
version = "3.41.0"

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

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

[[Crayons]]
git-tree-sha1 = "249fe38abf76d48563e2f4556bebd215aa317e15"
uuid = "a8cc5b0e-0ffa-5ad4-8c14-923d3ee1735f"
version = "4.1.1"

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

[[DataFrames]]
deps = ["Compat", "DataAPI", "Future", "InvertedIndices", "IteratorInterfaceExtensions", "LinearAlgebra", "Markdown", "Missings", "PooledArrays", "PrettyTables", "Printf", "REPL", "Reexport", "SortingAlgorithms", "Statistics", "TableTraits", "Tables", "Unicode"]
git-tree-sha1 = "ae02104e835f219b8930c7664b8012c93475c340"
uuid = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0"
version = "1.3.2"

[[DataStructures]]
deps = ["Compat", "InteractiveUtils", "OrderedCollections"]
git-tree-sha1 = "3daef5523dd2e769dad2365274f760ff5f282c7d"
uuid = "864edb3b-99cc-5e75-8d2d-829cb0a9cfe8"
version = "0.18.11"

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

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

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

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

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

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

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

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

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

[[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"

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

[[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"

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

[[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"

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

[[Future]]
deps = ["Random"]
uuid = "9fa8497b-333b-5362-9e8d-4d0656e87820"

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

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

[[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 = "aa22e1ee9e722f1da183eb33370df4c1aeb6c2cd"
uuid = "d2c73de3-f751-5644-a686-071e5b155ba9"
version = "0.63.1+0"

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

[[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"

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

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

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

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

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

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

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

[[InverseFunctions]]
deps = ["Test"]
git-tree-sha1 = "a7254c0acd8e62f1ac75ad24d5db43f5f19f3c65"
uuid = "3587e190-3f89-42d0-90ee-14403ec27112"
version = "0.1.2"

[[InvertedIndices]]
git-tree-sha1 = "bee5f1ef5bf65df56bdd2e40447590b272a5471f"
uuid = "41ab1584-1d38-5bbf-9106-f11c6c58b48f"
version = "1.1.0"

[[IrrationalConstants]]
git-tree-sha1 = "7fd44fd4ff43fc60815f8e764c0f352b83c49151"
uuid = "92d709cd-6900-40b7-9082-c6be49f344b6"
version = "0.1.1"

[[IterTools]]
git-tree-sha1 = "fa6287a4469f5e048d763df38279ee729fbd44e5"
uuid = "c8e1da08-722c-5040-9ed9-7db0dc04731e"
version = "1.4.0"

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

[[JLLWrappers]]
deps = ["Preferences"]
git-tree-sha1 = "22df5b96feef82434b07327e2d3c770a9b21e023"
uuid = "692b3bcd-3c85-4b1f-b108-f13ce0eb3210"
version = "1.4.0"

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

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

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

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

[[LaTeXStrings]]
git-tree-sha1 = "f2355693d6778a178ade15952b7ac47a4ff97996"
uuid = "b964fa9f-0449-5b57-a5c2-d3ea65f4040f"
version = "1.3.0"

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

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

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

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

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

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

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

[[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"

[[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"

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

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

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

[[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"

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

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

[[LogExpFunctions]]
deps = ["ChainRulesCore", "ChangesOfVariables", "DocStringExtensions", "InverseFunctions", "IrrationalConstants", "LinearAlgebra"]
git-tree-sha1 = "e5718a00af0ab9756305a0392832c8952c7426c1"
uuid = "2ab3a3ac-af41-5b50-aa03-7779005ae688"
version = "0.3.6"

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

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

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

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

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

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

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

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

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

[[NaNMath]]
git-tree-sha1 = "b086b7ea07f8e38cf122f5016af580881ac914fe"
uuid = "77ba4419-2d1f-58cd-9bb1-8ffee604a2e3"
version = "0.3.7"

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

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

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

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

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

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

[[Parsers]]
deps = ["Dates"]
git-tree-sha1 = "0b5cfbb704034b5b4c1869e36634438a047df065"
uuid = "69de0a69-1ddd-5017-9359-2bf0b02dc9f0"
version = "2.2.1"

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

[[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"

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

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

[[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", "UnicodeFun", "Unzip"]
git-tree-sha1 = "7e4920a7d4323b8ffc3db184580598450bde8a8e"
uuid = "91a5bcdd-55d7-5caf-9e0b-520d859cae80"
version = "1.25.7"

[[PooledArrays]]
deps = ["DataAPI", "Future"]
git-tree-sha1 = "db3a23166af8aebf4db5ef87ac5b00d36eb771e2"
uuid = "2dfb63ee-cc39-5dd5-95bd-886bf059d720"
version = "1.4.0"

[[Preferences]]
deps = ["TOML"]
git-tree-sha1 = "2cf929d64681236a2e074ffafb8d568733d2e6af"
uuid = "21216c6a-2e73-6563-6e65-726566657250"
version = "1.2.3"

[[PrettyTables]]
deps = ["Crayons", "Formatting", "Markdown", "Reexport", "Tables"]
git-tree-sha1 = "dfb54c4e414caa595a1f2ed759b160f5a3ddcba5"
uuid = "08abe8d2-0d0c-5749-adfa-8a2ac140af0d"
version = "1.3.1"

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

[[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"

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

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

[[RecipesBase]]
git-tree-sha1 = "6bf3f380ff52ce0832ddd3a2a7b9538ed1bcca7d"
uuid = "3cdcf5f2-1ef4-517c-9805-6587b60abb01"
version = "1.2.1"

[[RecipesPipeline]]
deps = ["Dates", "NaNMath", "PlotUtils", "RecipesBase"]
git-tree-sha1 = "37c1631cb3cc36a535105e6d5557864c82cd8c2b"
uuid = "01d81517-befc-4cb6-b9ec-a95719d0359c"
version = "0.5.0"

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

[[RelocatableFolders]]
deps = ["SHA", "Scratch"]
git-tree-sha1 = "cdbd3b1338c72ce29d9584fdbe9e9b70eeb5adca"
uuid = "05181044-ff0b-4ac5-8273-598c1e38db00"
version = "0.1.3"

[[Requires]]
deps = ["UUIDs"]
git-tree-sha1 = "838a3a4188e2ded87a4f9f184b4b0d78a1e91cb7"
uuid = "ae029012-a4dd-5104-9daa-d747884805df"
version = "1.3.0"

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

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

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

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

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

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

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

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

[[StaticArrays]]
deps = ["LinearAlgebra", "Random", "Statistics"]
git-tree-sha1 = "2884859916598f974858ff01df7dfc6c708dd895"
uuid = "90137ffa-7385-5640-81b9-e52037218182"
version = "1.3.3"

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

[[StatsAPI]]
git-tree-sha1 = "d88665adc9bcf45903013af0982e2fd05ae3d0a6"
uuid = "82ae8749-77ed-4fe6-ae5f-f523153014b0"
version = "1.2.0"

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

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

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

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

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

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

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

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

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

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

[[UnicodeFun]]
deps = ["REPL"]
git-tree-sha1 = "53915e50200959667e78a92a418594b428dffddf"
uuid = "1cfade01-22cf-5700-b092-accc4b62d6e1"
version = "0.4.1"

[[Unzip]]
git-tree-sha1 = "34db80951901073501137bdbc3d5a8e7bbd06670"
uuid = "41fe7b60-77ed-43a1-b4f0-825fd5a5650d"
version = "0.1.2"

[[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"

[[Wayland_protocols_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "66d72dc6fcc86352f01676e8f0f698562e60510f"
uuid = "2381bf8a-dfd0-557d-9999-79630e7b1b91"
version = "1.23.0+0"

[[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"

[[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"

[[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"

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

[[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"

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

[[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"

[[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"

[[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"

[[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"

[[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"

[[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"

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

[[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"

[[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"

[[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"

[[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"

[[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"

[[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"

[[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"

[[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"

[[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"

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

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

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

[[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"

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

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

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

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

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

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

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

[[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:
# ╟─266c7f54-ce35-4b97-bdb6-bb5611332811
# ╟─5000b8f3-8a09-4440-80e9-ab56325de90f
# ╟─d6285877-636a-4804-8790-7e4525d870b9
# ╟─c6af78f8-d0f2-48ed-b607-7c09dd3d535d
# ╟─7cb56496-5184-44ad-9323-db908a8253c8
# ╟─f398de0e-f8e6-4f0f-931e-aa015d2aeb7e
# ╠═4265b668-3c60-4859-98e6-71e65e8dccd8
# ╟─66d7232f-c7b7-4385-95b8-460b0e570105
# ╟─4bc3066e-a0f5-4829-9c72-fa9cb6046427
# ╟─af094e89-71e5-4468-93a9-941a1c32f8ff
# ╟─8147f6ce-16ac-4085-a5d5-ef3c863d1018
# ╟─4c7e1677-bd51-475d-b996-1a3bf2d31ae2
# ╟─24785674-8024-4d9e-9bb3-8b5e4589e7b5
# ╟─52aaf73e-7d97-43e6-810d-f3a8eea2e081
# ╟─d84017c8-3e45-495d-8748-e758cca32932
# ╟─aca14538-cc05-49bd-9371-f4358e70150e
# ╟─78bb0c77-8722-4854-aa74-d502525469c5
# ╟─92652f0b-8112-4ed9-9412-ed714e66b2f8
# ╟─9350e66f-bfa0-4772-a8c9-8d42df4c76ed
# ╟─ad3efd53-7051-4007-a276-b1b91aa76339
# ╟─f8b45b20-1a32-49c1-ad84-26e165328614
# ╟─a7c46cef-e37d-41ee-acfa-234c527906cf
# ╠═23a2aa94-aee7-44d3-9658-d41724081b0a
# ╟─00000000-0000-0000-0000-000000000001
# ╟─00000000-0000-0000-0000-000000000002

max_stars_repo_name: licollier/Multiobjectopt

max_issues_repo_name: licollier/Multiobjectopt

max_forks_repo_name: licollier/Multiobjectopt


text:
(f::NoForcing)(dt,s) = nothing
initialize!(f::NoForcing,s) = nothing

@inline proj(a::Complex,b::Complex) = muladd(a.re, b.re, a.im*b.im)

@par function (F::RfForcing)(s::@par(AbstractSimulation))

    cPlaneNumber = 1
    dt = get_dt(s)
    Tf = getTf(F)
    #ts = 10*dt
    ts = dt/get_cfl(s)

    it = s.iteration[]

    if has_variable_timestep(s)
        if it == 0
            ts /= 0.1
        elseif it == 1
            ts /= 0.2
        elseif it == 2
            ts /= 0.4
        elseif it == 3
            ts /= 0.8
        end
    end

    omega = (2*π/(Tf*ts))
    alpha = getalpha(F)
    eps = Base.eps()
    _kf = getKf(F)
    maxdk = getmaxdk(F)
    avgWaveNumInShell2d = getavgk(F)
    nShells2d = length(avgWaveNumInShell2d)

    Ef = F.Ef
    R = F.R
    Em = F.Em
    Zf = getZf(F)
    factor = F.factor

    s1 = fill!(F.forcex,0)
    s2 = fill!(F.forcey,0)

    u1 = s.u.c.x
    u2 = s.u.c.y
    u3 = s.u.c.z

    # // get current spectrum for k=1 plane
    calculate_u1u2_spectrum!(Ef,s.u, cPlaneNumber)

    @inbounds for i=2:nShells2d
        if avgWaveNumInShell2d[i] <= _kf
            R[i] += dt*(-2*alpha*omega*R[i] - omega*omega*(Ef[i] - Em[i]))
            R[i]=max(0.0, R[i])
            factor[i] = fsqrt(R[i]/max(Ef[i],eps))*Zf[i]*dt
        end
    end

    umag = 0.0
  #  # -------------------- Horizontal Forcing --------------------
    ff = 0.0
    fv = 0.0

    @inbounds for j=YRANGE
        conjFactX=1.0
        for i=XRANGE
            k = fsqrt(muladd(KX[i],KX[i],KY[j]^2))
            n = round(Int,k/maxdk) + 1
            if (1 < n <= nShells2d)
                if avgWaveNumInShell2d[n] <= _kf
                    s1[i,j,1] = u1[i,j,1]*factor[n]
                    s2[i,j,1] = u2[i,j,1]*factor[n]
                    ff += (abs2(s1[i,j,1]) + abs2(s2[i,j,1]))*conjFactX
                    fv += (proj(u1[i,j,1],s1[i,j,1]) + proj(u2[i,j,1],s2[i,j,1]))*conjFactX
                end
            end
            conjFactX=2.0
        end
    end
    ff = ff*0.5/dt
    fv = fv/dt
    horizontalPower = ff+fv
    F.hp[] = horizontalPower
    powerFraction = 0.99

    # # -------------------- Vertical Forcing --------------------
    # /*
    #   Force the points with kx=ky=0 and kz=1,2,3,4,5 so that the power
    #   added is (1-powerFraction) of that added to the horizontal */
    ff = 0.0
    fv = 0.0
    umag = 0.0
    #     // get the sum of the existing velocites
    @inbounds for k = 2:6
        umag += fsqrt(abs2(u1[1,1,k]) + abs2(u2[1,1,k])) + fsqrt(abs2(u1[1,1,NZ-k+2]) + abs2(u2[1,1,NZ-k+2]))
    end

    f = dt*sqrt(2.0*horizontalPower*(1.0-powerFraction))/umag

    @inbounds for k=2:6
        s1[1,1,k] = u1[1,1,k]*f
        s2[1,1,k] = u2[1,1,k]*f
        s1[1,1,NZ-k+2] = u1[1,1,NZ-k+2]*f
        s2[1,1,NZ-k+2] = u2[1,1,NZ-k+2]*f
        ff += abs2(s1[1,1,k]) + abs2(s2[1,1,k]) + abs2(s1[1,1,NZ-k+2]) + abs2(s2[1,1,NZ-k+2])
        fv += proj(u1[1,1,k],s1[1,1,k]) + proj(u2[1,1,k],s2[1,1,k]) + proj(u1[1,1,NZ-k+2],s1[1,1,NZ-k+2]) + proj(u2[1,1,NZ-k+2],s2[1,1,NZ-k+2])
    end
    ff = ff*0.5/dt
    fv = fv/dt
    verticalPower = ff+fv
    F.vp[] = verticalPower
    return 1/dt
end