text:
using AstroTime: Epoch, TimeScale
using LinearAlgebra: promote_leaf_eltypes
using StaticArrays: SVector

using ..Bodies: CelestialBody, earth, grav_param
using ..Frames: AbstractFrame, icrf

import Base: ==
import ..Interfaces: AbstractState,
    centralbody,
    epoch,
    position,
    refframe,
    state,
    timescale,
    velocity
import ..TwoBody: period, cartesian, keplerian

export State, KeplerianState, pos_type, vel_type, period

function period(s::AbstractState)
    μ = grav_param(body(s))
    a, _ = keplerian(s)
    return period(a, μ)
end

struct State{S, F, B, T, TP, TV} <: AbstractState{S, F, B, T}
    epoch::Epoch{S, T}
    pos::SVector{3, TP}
    vel::SVector{3, TV}
    function State(epoch::Epoch{S, T}, pos, vel;
                   scale::TimeScale=timescale(epoch),
                   frame::F=icrf,
                   body::B=earth) where {S, F, B, T}
        TP = eltype(pos)
        TV = eltype(vel)
        ep = Epoch{scale}(epoch)
        new{scale::TimeScale, frame::AbstractFrame, body::CelestialBody, T, TP, TV}(ep, pos, vel)
    end
end

Base.getindex(s::State, i::Int) = getindex(s, Val(i))
Base.getindex(s::State, ::Val{1}) = s.pos[1]
Base.getindex(s::State, ::Val{2}) = s.pos[2]
Base.getindex(s::State, ::Val{3}) = s.pos[3]
Base.getindex(s::State, ::Val{4}) = s.vel[1]
Base.getindex(s::State, ::Val{5}) = s.vel[2]
Base.getindex(s::State, ::Val{6}) = s.vel[3]

function (==)(s1::State, s2::State)
    s1.epoch == s2.epoch && s1.pos == s2.pos && s1.vel == s2.vel
end

function Base.isapprox(s1::State, s2::State, atol::Real=0,
                       rtol::Real=Base.rtoldefault(promote_leaf_eltypes(s1), promote_leaf_eltypes(s2), atol))
    isapprox(s1.epoch, s2.epoch, atol=atol, rtol=rtol) &&
    isapprox(s1.pos, s2.pos, atol=atol, rtol=rtol) &&
    isapprox(s1.vel, s2.vel, atol=atol, rtol=rtol)
end

pos_type(s::State{S, F, B, T, TP}) where {S, F, B, T, TP} = TP
vel_type(s::State{S, F, B, T, TP, TV}) where {S, F, B, T, TP, TV} = TV

epoch(s::State) = s.epoch
position(s::State) = s.pos
velocity(s::State) = s.vel
state(s::State) = (s.pos, s.vel)
keplerian(s::State) = keplerian(position(s), velocity(s), grav_param(centralbody(s)))

struct KeplerianState{Scale, Frame, Body, T} <: AbstractState{Scale, Frame, Body, T}
    epoch::Epoch{Scale, T}
    a::T
    e::T
    i::T
    Ω::T
    ω::T
    ν::T
    function KeplerianState(epoch::Epoch{Scale, T}, a, e, i, Ω, ω, ν;
                            scale::TimeScale=timescale(epoch),
                            frame::Frame=icrf, body::Body=earth) where {Scale, Frame, Body, T}
        ep = Epoch{scale}(epoch)
        new{scale::TimeScale, frame::AbstractFrame, body::CelestialBody, T}(ep, a, e, i, Ω, ω, ν)
    end
end

function Base.getindex(s::KeplerianState, i::Int)
    i == 1 && return s.a
    i == 2 && return s.e
    i == 3 && return s.i
    i == 4 && return s.Ω
    i == 5 && return s.ω
    i == 6 && return s.ν
end

function (==)(s1::KeplerianState, s2::KeplerianState)
    return s1.epoch == s2.epoch &&
        s1.a == s2.a &&
        s1.e == s2.e &&
        s1.i == s2.i &&
        s1.Ω == s2.Ω &&
        s1.ω == s2.ω &&
        s1.ν == s2.ν
end

function Base.isapprox(s1::KeplerianState, s2::KeplerianState,
                       atol::Real=0,
                       rtol::Real=Base.rtoldefault(promote_leaf_eltypes(s1), promote_leaf_eltypes(s2), atol))
    isapprox(s1.epoch, s2.epoch, atol=atol, rtol=rtol) &&
    isapprox(s1.a, s2.a, atol=atol, rtol=rtol) &&
    isapprox(s1.e, s2.e, atol=atol, rtol=rtol) &&
    isapprox(s1.i, s2.i, atol=atol, rtol=rtol) &&
    isapprox(s1.Ω, s2.Ω, atol=atol, rtol=rtol) &&
    isapprox(s1.ω, s2.ω, atol=atol, rtol=rtol) &&
    isapprox(s1.ν, s2.ν, atol=atol, rtol=rtol)
end

Base.eltype(::KeplerianState{_S, _F, _B, T}) where {_S, _F, _B, T} = T

epoch(s::KeplerianState) = s.epoch
position(s::KeplerianState) = cartesian(s.a, s.e, s.i, s.Ω, s.ω, s.ν, grav_param(body(s)))[1]
velocity(s::KeplerianState) = cartesian(s.a, s.e, s.i, s.Ω, s.ω, s.ν, grav_param(body(s)))[2]
state(s::KeplerianState) = cartesian(s.a, s.e, s.i, s.Ω, s.ω, s.ν, grav_param(body(s)))
keplerian(s::KeplerianState) = (s.a, s.e, s.i, s.Ω, s.ω, s.ν)

KeplerianState(s::AbstractState) = KeplerianState(epoch(s), keplerian(s)...; frame=refframe(s), body=centralbody(s))
State(s::KeplerianState) = State(epoch(s), state(s)...; frame=refframe(s), body=body(s))

# struct ThreeBodyState{
#         F<:Frame,
#         T,
#         C1<:CelestialBody,
#         C2<:CelestialBody,
#     } <: AbstractState
#     ep::Epoch{T}
#     r::SVector{3,Float64}
#     v::SVector{3,Float64}
#
#     function ThreeBodyState(
#         ep::Epoch{T}, r, v, frame::Type{F}=GCRF,
#         primary::Type{C1}=Sun, secondary::Type{C2}=Earth
#     ) where {T,F<:Frame,C1<:CelestialBody,C2<:CelestialBody}
#         new{F, T, C1, C2}(ep, r, v)
#     end
# end
#
# frame(::ThreeBodyState{F}) where F<:Frame = F
# timescale(::ThreeBodyState{<:Frame, T}) where T = T
# primary(::ThreeBodyState{<:Frame,,C}) where C<:CelestialBody = C
# secondary(::ThreeBodyState{<:Frame,,<:CelestialBody,C}) where {
#     C<:CelestialBody} = C


text:
### Julia OpenStreetMap Package ###
### MIT License                 ###
### Copyright 2014              ###

### Crop map elements without copying data ###
function cropMap!(nodes::@compat(Union{Dict{Int,LLA},Dict{Int,ENU}}), bounds::Bounds;
                  highways::@compat(Union{@compat(Void),Dict{Int,Highway}}) = nothing,
                  buildings::@compat(Union{@compat(Void),Dict{Int,Building}}) = nothing,
                  features::@compat(Union{@compat(Void),Dict{Int,Feature}}) = nothing,
                  delete_nodes::Bool=true)

    if !isa(highways, @compat(Void))
        crop!(nodes, bounds, highways)
    end
    if !isa(buildings, @compat(Void))
        crop!(nodes, bounds, buildings)
    end
    if !isa(features, @compat(Void))
        crop!(nodes, bounds, features)
    end

    if delete_nodes
        crop!(nodes, bounds)
    end

    return nothing
end

### Crop nodes ###
function crop!(nodes::Dict, bounds::Bounds)
    for (key, node) in nodes
        if !inBounds(node, bounds)
            delete!(nodes, key)
        end
    end

    return nothing
end

### Crop highways ###
function crop!(nodes::Dict, bounds::Bounds, highways::Dict{Int,Highway})
    missing_nodes = Int[]

    for (key, highway) in highways
        valid = falses(length(highway.nodes))
        n = 1
        while n <= length(highway.nodes)
            if haskey(nodes, highway.nodes[n])
                valid[n] = inBounds(nodes[highway.nodes[n]], bounds)
                n += 1
            else
                push!(missing_nodes, highway.nodes[n])
                splice!(highway.nodes, n)
                splice!(valid, n)
            end
        end

        nodes_in_bounds = sum(valid)

        if nodes_in_bounds == 0
            delete!(highways, key)   # Remove highway from list
        elseif nodes_in_bounds < length(valid)
            cropHighway!(nodes, bounds, highway, valid) # Crop highway length
        end
    end

    if length(missing_nodes) > 0
        warn("$(length(missing_nodes)) missing nodes were removed from highways.")
    end

    return missing_nodes
end

### Crop buildings ###
function crop!(nodes::Dict, bounds::Bounds, buildings::Dict{Int,Building})
    for (key, building) in buildings
        valid = falses(length(building.nodes))
        for n = 1:length(building.nodes)
            if haskey(nodes, building.nodes[n])
                valid[n] = inBounds(nodes[building.nodes[n]], bounds)
            end
        end

        nodes_in_bounds = sum(valid)
        if nodes_in_bounds == 0
            delete!(buildings, key)   # Remove building from list
        elseif nodes_in_bounds < length(valid)
            # TODO: Interpolate buildings to bounds?
            delete!(buildings, key)   # Remove building from list
        end
    end

    return nothing
end

### Crop features ###
function crop!(nodes::Dict, bounds::Bounds, features::Dict{Int,Feature})
    for key in keys(features)
        if !haskey(nodes, key) || !inBounds(nodes[key], bounds)
            delete!(features, key)
        end
    end

    return nothing
end

function cropHighway!(nodes::Dict, bounds::Bounds, highway::Highway, valids::BitVector)
    prev_id, prev_valid = highway.nodes[1], valids[1]
    ni = 1
    for valid in valids
        id = highway.nodes[ni]

        if !valid
            deleteat!(highway.nodes, ni)
            ni -= 1
        end
        if valid != prev_valid
            prev_node, node = nodes[prev_id], nodes[id]
            if !(Geodesy.onBounds(prev_node, bounds) ||
                 Geodesy.onBounds(node, bounds))
                new_node = Geodesy.boundaryPoint(prev_node, node, bounds)
                new_id = addNewNode!(nodes, new_node)
                insert!(highway.nodes, ni + !valid, new_id)
                ni += 1
            end
        end

        ni += 1

        prev_id, prev_valid = id, valid
    end

    return nothing
end

ext: jl


text:
using NumericalMethodsforEngineers
using Test

@sym begin
  ClearAll(x, y, sol)
  sol1 = DSolve(D(y(t),t) - y(t) + Sin(t), y(t))
  Print("DSolve(D(y(t),t) - y(t) + Sin(t), y(t)) = $(sol1)\n")
  #sol2 = Roots(D(x^4+1,x,2),x)
  #Println(sol2)
end


text:
using OrdinaryDiffEq
using LabelledArrays

function f(out,du,u,p,t)
  out.x = - 0.04u.x              + 1e4*u.y*u.z - du.x
  out.y = + 0.04u.x - 3e7*u.y^2 - 1e4*u.y*u.z - du.y
  out.z = u.x + u.y + u.z - 1.0
end

u₀ = LVector(x=1.0, y=0.0, z=0.0)
du₀ = LVector(x=-0.04, y=0.04, z=0.0)
tspan = (0.0,100000.0)

differential_vars = LVector(x=true, y=true, z=false)
prob = DAEProblem(f,du₀,u₀,tspan,differential_vars=differential_vars)

sol = solve(prob, DImplicitEuler())

function f1(du,u,p,t)
   du.x .= -1 .* u.x .* u.y .* p[1]
   du.y .= -1 .* u.y .* p[2]
end
const n = 1000
u_0 = @LArray  fill(1000.0,2*n) (x = (1:n),y = (n+1:2*n))
p = [0.1,0.1]
prob1 = ODEProblem(f1,u_0,(0,100.0),p)
sol = solve(prob1, Rodas5())
sol = solve(prob1, Rodas5(autodiff=false))


text:
"""
    make_multinetwork(sn_data, time_series; global_keys, number_of_nws, nw_id_offset)

Generate a multinetwork data structure from a single network and a time series.

# Arguments
- `sn_data`: single-network data structure to be replicated.
- `time_series`: data structure containing the time series.
- `global_keys`: keys that are stored once per multinetwork (they are not repeated in each
  `nw`).
- `number_of_nws`: number of networks to be created from `sn_data` and `time_series`;
  default: read from `dim`.
- `nw_id_offset`: optional value to be added to `time_series` ids to shift `nw` ids in
  multinetwork data structure; default: read from `dim`.
- `check_dim`: whether to check for `dim` in `sn_data`; default: `true`.
"""
function make_multinetwork(
        sn_data::Dict{String,Any},
        time_series::Dict{String,Any};
        global_keys = ["dim","multinetwork","name","per_unit","source_type","source_version"],
        number_of_nws::Int = length(dim(sn_data)[:li]),
        nw_id_offset::Int = dim(sn_data)[:offset],
        check_dim::Bool = true
    )

    if _IM.ismultinetwork(sn_data)
        Memento.error(_LOGGER, "`sn_data` argument must be a single network.")
    end
    if check_dim && !haskey(sn_data, "dim")
        Memento.error(_LOGGER, "Missing `dim` dict in `sn_data` argument. The function `add_dimension!` must be called before `make_multinetwork`.")
    end

    mn_data = Dict{String,Any}("nw"=>Dict{String,Any}())
    _add_mn_global_values!(mn_data, sn_data, global_keys)
    _add_time_series!(mn_data, sn_data, global_keys, time_series, number_of_nws, nw_id_offset)

    return mn_data
end

"""
    make_multinetwork(sn_data; global_keys)

Generate a multinetwork data structure - having only one `nw` - from a single network.

# Arguments
- `sn_data`: single-network data structure to be replicated.
- `global_keys`: keys that are stored once per multinetwork (they are not repeated in each
  `nw`).
- `check_dim`: whether to check for `dim` in `sn_data`; default: `true`.
"""
function make_multinetwork(
        sn_data::Dict{String,Any};
        global_keys = ["dim","name","per_unit","source_type","source_version"],
        check_dim::Bool = true
    )

    if _IM.ismultinetwork(sn_data)
        Memento.error(_LOGGER, "`sn_data` argument must be a single network.")
    end
    if check_dim && !haskey(sn_data, "dim")
        Memento.error(_LOGGER, "Missing `dim` dict in `sn_data` argument. The function `add_dimension!` must be called before `make_multinetwork`.")
    end

    mn_data = Dict{String,Any}("nw"=>Dict{String,Any}())
    _add_mn_global_values!(mn_data, sn_data, global_keys)
    template_nw = _make_template_nw(sn_data, global_keys)
    mn_data["nw"]["1"] = copy(template_nw)

    return mn_data
end

"""
    shift_nws!(mn_data, offset=dim_length(mn_data))

Shift by `offset` the networks in `mn_data`.

The `offset` argument is added to the existing offset.
Return the updated `mn_data` variable.
`mn_data` must be a multinetwork `data` dictionary.
If possible, use `shift_ids!` instead.

See also: `shift_ids!`.
"""
function shift_nws!(mn_data::Dict{String,Any}, offset::Int=dim_length(mn_data))
    if !_IM.ismultinetwork(mn_data)
        Memento.error(_LOGGER, "`mn_data` argument must be a multinetwork.")
    end
    shift_ids!(mn_data["dim"], offset)
    shifted_nw = Dict{String,Any}()
    for (n,nw) in mn_data["nw"]
        shifted_nw["$(parse(Int,n)+offset)"] = nw
    end
    mn_data["nw"] = shifted_nw
    return mn_data
end

"""
    import_nws!(mn_data, others...)

Import into `mn_data["nw"]` the `nw`s contained in `others`.

`nw` ids of the two multinetworks must be contiguous (an error is raised otherwise).

See also: `merge_multinetworks!`.
"""
function import_nws!(mn_data::Dict{String,Any}, others::Dict{String,Any}...)
    if !_IM.ismultinetwork(mn_data)
        Memento.error(_LOGGER, "`import_nws!` can only be applied to multinetwork data dictionaries.")
    end
    for other in others
        if !isempty(keys(mn_data["nw"]) ∩ keys(other["nw"]))
            Memento.error(_LOGGER, "Attempting to import multinetworks having overlapping `nw` ids.")
        end
        merge!(mn_data["nw"], other["nw"])
    end
    first_id, last_id = extrema(parse.(Int,keys(mn_data["nw"])))
    if length(mn_data["nw"]) != last_id - first_id + 1
        Memento.error(_LOGGER, "The ids of the imported `nw`s must be contiguous.")
    end
    return mn_data
end

"""
    merge_multinetworks!(mn_data_1, mn_data_2, dimension)

Merge `mn_data_2` into `mn_data_1` along `dimension`.

`nw` ids of the two multinetworks must be contiguous (an error is raised otherwise).
Fields present in `mn_data_1` but not in `mn_data_2` are shallow-copied into `mn_data_1`.
Fields present in both multinetworks must be equal, except for `dim`, `nw` and possibly for
`name`.

See also: `import_nws!`.
"""
function merge_multinetworks!(mn_data_1::Dict{String,Any}, mn_data_2::Dict{String,Any}, dimension::Symbol)
    for k in ("dim", "nw")
        for data in (mn_data_1, mn_data_2)
            if k ∉ keys(data)
                Memento.error(_LOGGER, "Missing field $k from input data dictionary.")
            end
        end
    end

    mn_data_1["dim"] = merge_dim!(mn_data_1["dim"], mn_data_2["dim"], dimension)

    import_nws!(mn_data_1, mn_data_2)

    keys1 = setdiff(keys(mn_data_1), ("dim", "nw"))
    keys2 = setdiff(keys(mn_data_1), ("dim", "nw"))
    for k in keys1 ∩ keys2
        if mn_data_1[k] == mn_data_2[k]
            continue
        elseif k == "name" # Applied only if names are different
            mn_data_1["name"] = "Merged multinetwork"
        else
            Memento.error(_LOGGER, "Attempting to merge multinetworks that differ on the value of \"$k\".")
        end
    end
    for k in setdiff(keys2, keys1)
        mn_data_1[k] = mn_data_2[k]
    end
    return mn_data_1
end

"""
    slice = slice_multinetwork(data::Dict{String,Any}; kwargs...)

Slice a multinetwork keeping the networks that have the coordinates specified by `kwargs`.

`kwargs` must be of the form `name = <value>`, where `name` is the name of a dimension of
`dim` and `<value>` is an `Int` coordinate of that dimension.

Return a sliced multinetwork that shares its data with `data`.
The coordinates of the dimensions at which the original multinetwork is sliced are
accessible with `dim_meta(slice, <name>, "orig_id")` where `<name>` is the name of one of
those dimensions.
Forward and backward lookup dicts containing the network ids of `data` and `slice` are
accessible with `slice["slice"]["slice_orig_nw_lookup"]` and
`slice["slice"]["orig_slice_nw_lookup"]`.
"""
function slice_multinetwork(data::Dict{String,Any}; kwargs...)
    slice = Dict{String,Any}()
    for k in setdiff(keys(data), ("dim", "nw"))
        slice[k] = data[k]
    end
    dim_dict, ids = slice_dim(dim(data); kwargs...)
    slice["dim"] = dim_dict
    slice["nw"] = Dict{String,Any}()
    for (new_id, old_id) in enumerate(ids)
        slice["nw"]["$new_id"] = data["nw"]["$old_id"]
    end
    slice["slice"] = Dict{String,Any}()
    slice["slice"]["slice_orig_nw_lookup"] = Dict(enumerate(ids))
    slice["slice"]["orig_slice_nw_lookup"] = Dict((o,s) for (s,o) in slice["slice"]["slice_orig_nw_lookup"])
    return slice
end

# Copy global values from sn_data to mn_data handling special cases
function _add_mn_global_values!(mn_data, sn_data, global_keys)

    # Insert global values into mn_data by copying from sn_data
    for k in global_keys
        if haskey(sn_data, k)
            mn_data[k] = sn_data[k]
        end
    end

    # Special cases are handled below
    mn_data["multinetwork"] = true
    get!(mn_data, "name", "multinetwork")
end

# Make a copy of `data` and remove global keys
function _make_template_nw(sn_data, global_keys)
    template_nw = copy(sn_data)
    for k in global_keys
        delete!(template_nw, k)
    end
    return template_nw
end

# Build multinetwork data structure: for each network, replicate the template and replace with data from time_series
function _add_time_series!(mn_data, sn_data, global_keys, time_series, number_of_nws, offset)
    template_nw = _make_template_nw(sn_data, global_keys)
    for time_series_idx in 1:number_of_nws
        n = time_series_idx + offset
        mn_data["nw"]["$n"] = _build_nw(template_nw, time_series, time_series_idx)
    end
end

# Build the nw by shallow-copying the template and substituting data from time_series only if is different.
function _build_nw(template_nw, time_series, idx)
    nw = copy(template_nw)
    for (key, element) in time_series
        if haskey(nw, key)
            nw[key] = copy(template_nw[key])
            for (l, element) in time_series[key]
                if haskey(nw[key], l)
                    nw[key][l] = copy(template_nw[key][l])
                    for (m, property) in time_series[key][l]
                        nw[key][l][m] = property[idx]
                    end
                else
                    Memento.warn(_LOGGER, "Key $l not found, will be ignored.")
                end
            end
        else
            Memento.warn(_LOGGER, "Key $key not found, will be ignored.")
        end
    end
    return nw
end


text:
#reload("test-dists.jl")
reload("test-conj.jl")
reload("test-non-conj.jl")


text:
using JuMP, EAGO

                     m = Model()

                     EAGO.register_eago_operators!(m)

                     @variable(m, -1 <= x[i=1:3] <= 1)

                     @variable(m, -3.428579430434188 <= q <= 8.991868736935128)

                     add_NL_constraint(m, :((0.758903986598098 + 0.8106379052679875*(0.47487042435595583 + 0.4488775132618512*(0.1716391672055586 + 0.7301849089692007*(0.33202390613731003 + -0.8931954910636541*$(x[1]) + 0.7142724585602056*$(x[2]) + -0.28852147983722487*$(x[3]))/(1 + exp(-(0.33202390613731003 + -0.8931954910636541*$(x[1]) + 0.7142724585602056*$(x[2]) + -0.28852147983722487*$(x[3])))) + 0.6276077641275091*(-0.8935890604396688 + -0.29936605585485676*$(x[1]) + -0.5391102865466948*$(x[2]) + 0.8633503800224367*$(x[3]))/(1 + exp(-(-0.8935890604396688 + -0.29936605585485676*$(x[1]) + -0.5391102865466948*$(x[2]) + 0.8633503800224367*$(x[3])))))/(1 + exp(-(0.1716391672055586 + 0.7301849089692007*(0.33202390613731003 + -0.8931954910636541*$(x[1]) + 0.7142724585602056*$(x[2]) + -0.28852147983722487*$(x[3]))/(1 + exp(-(0.33202390613731003 + -0.8931954910636541*$(x[1]) + 0.7142724585602056*$(x[2]) + -0.28852147983722487*$(x[3])))) + 0.6276077641275091*(-0.8935890604396688 + -0.29936605585485676*$(x[1]) + -0.5391102865466948*$(x[2]) + 0.8633503800224367*$(x[3]))/(1 + exp(-(-0.8935890604396688 + -0.29936605585485676*$(x[1]) + -0.5391102865466948*$(x[2]) + 0.8633503800224367*$(x[3]))))))) + 0.015398554931854491*(0.8366427516313624 + 0.8654420505988725*(0.33202390613731003 + -0.8931954910636541*$(x[1]) + 0.7142724585602056*$(x[2]) + -0.28852147983722487*$(x[3]))/(1 + exp(-(0.33202390613731003 + -0.8931954910636541*$(x[1]) + 0.7142724585602056*$(x[2]) + -0.28852147983722487*$(x[3])))) + -0.07448940361379819*(-0.8935890604396688 + -0.29936605585485676*$(x[1]) + -0.5391102865466948*$(x[2]) + 0.8633503800224367*$(x[3]))/(1 + exp(-(-0.8935890604396688 + -0.29936605585485676*$(x[1]) + -0.5391102865466948*$(x[2]) + 0.8633503800224367*$(x[3])))))/(1 + exp(-(0.8366427516313624 + 0.8654420505988725*(0.33202390613731003 + -0.8931954910636541*$(x[1]) + 0.7142724585602056*$(x[2]) + -0.28852147983722487*$(x[3]))/(1 + exp(-(0.33202390613731003 + -0.8931954910636541*$(x[1]) + 0.7142724585602056*$(x[2]) + -0.28852147983722487*$(x[3])))) + -0.07448940361379819*(-0.8935890604396688 + -0.29936605585485676*$(x[1]) + -0.5391102865466948*$(x[2]) + 0.8633503800224367*$(x[3]))/(1 + exp(-(-0.8935890604396688 + -0.29936605585485676*$(x[1]) + -0.5391102865466948*$(x[2]) + 0.8633503800224367*$(x[3]))))))))/(1 + exp(-(0.47487042435595583 + 0.4488775132618512*(0.1716391672055586 + 0.7301849089692007*(0.33202390613731003 + -0.8931954910636541*$(x[1]) + 0.7142724585602056*$(x[2]) + -0.28852147983722487*$(x[3]))/(1 + exp(-(0.33202390613731003 + -0.8931954910636541*$(x[1]) + 0.7142724585602056*$(x[2]) + -0.28852147983722487*$(x[3])))) + 0.6276077641275091*(-0.8935890604396688 + -0.29936605585485676*$(x[1]) + -0.5391102865466948*$(x[2]) + 0.8633503800224367*$(x[3]))/(1 + exp(-(-0.8935890604396688 + -0.29936605585485676*$(x[1]) + -0.5391102865466948*$(x[2]) + 0.8633503800224367*$(x[3])))))/(1 + exp(-(0.1716391672055586 + 0.7301849089692007*(0.33202390613731003 + -0.8931954910636541*$(x[1]) + 0.7142724585602056*$(x[2]) + -0.28852147983722487*$(x[3]))/(1 + exp(-(0.33202390613731003 + -0.8931954910636541*$(x[1]) + 0.7142724585602056*$(x[2]) + -0.28852147983722487*$(x[3])))) + 0.6276077641275091*(-0.8935890604396688 + -0.29936605585485676*$(x[1]) + -0.5391102865466948*$(x[2]) + 0.8633503800224367*$(x[3]))/(1 + exp(-(-0.8935890604396688 + -0.29936605585485676*$(x[1]) + -0.5391102865466948*$(x[2]) + 0.8633503800224367*$(x[3]))))))) + 0.015398554931854491*(0.8366427516313624 + 0.8654420505988725*(0.33202390613731003 + -0.8931954910636541*$(x[1]) + 0.7142724585602056*$(x[2]) + -0.28852147983722487*$(x[3]))/(1 + exp(-(0.33202390613731003 + -0.8931954910636541*$(x[1]) + 0.7142724585602056*$(x[2]) + -0.28852147983722487*$(x[3])))) + -0.07448940361379819*(-0.8935890604396688 + -0.29936605585485676*$(x[1]) + -0.5391102865466948*$(x[2]) + 0.8633503800224367*$(x[3]))/(1 + exp(-(-0.8935890604396688 + -0.29936605585485676*$(x[1]) + -0.5391102865466948*$(x[2]) + 0.8633503800224367*$(x[3])))))/(1 + exp(-(0.8366427516313624 + 0.8654420505988725*(0.33202390613731003 + -0.8931954910636541*$(x[1]) + 0.7142724585602056*$(x[2]) + -0.28852147983722487*$(x[3]))/(1 + exp(-(0.33202390613731003 + -0.8931954910636541*$(x[1]) + 0.7142724585602056*$(x[2]) + -0.28852147983722487*$(x[3])))) + -0.07448940361379819*(-0.8935890604396688 + -0.29936605585485676*$(x[1]) + -0.5391102865466948*$(x[2]) + 0.8633503800224367*$(x[3]))/(1 + exp(-(-0.8935890604396688 + -0.29936605585485676*$(x[1]) + -0.5391102865466948*$(x[2]) + 0.8633503800224367*$(x[3])))))))))) + -0.6668215058198093*(0.8216722410540171 + 0.5667551555087149*(0.1716391672055586 + 0.7301849089692007*(0.33202390613731003 + -0.8931954910636541*$(x[1]) + 0.7142724585602056*$(x[2]) + -0.28852147983722487*$(x[3]))/(1 + exp(-(0.33202390613731003 + -0.8931954910636541*$(x[1]) + 0.7142724585602056*$(x[2]) + -0.28852147983722487*$(x[3])))) + 0.6276077641275091*(-0.8935890604396688 + -0.29936605585485676*$(x[1]) + -0.5391102865466948*$(x[2]) + 0.8633503800224367*$(x[3]))/(1 + exp(-(-0.8935890604396688 + -0.29936605585485676*$(x[1]) + -0.5391102865466948*$(x[2]) + 0.8633503800224367*$(x[3])))))/(1 + exp(-(0.1716391672055586 + 0.7301849089692007*(0.33202390613731003 + -0.8931954910636541*$(x[1]) + 0.7142724585602056*$(x[2]) + -0.28852147983722487*$(x[3]))/(1 + exp(-(0.33202390613731003 + -0.8931954910636541*$(x[1]) + 0.7142724585602056*$(x[2]) + -0.28852147983722487*$(x[3])))) + 0.6276077641275091*(-0.8935890604396688 + -0.29936605585485676*$(x[1]) + -0.5391102865466948*$(x[2]) + 0.8633503800224367*$(x[3]))/(1 + exp(-(-0.8935890604396688 + -0.29936605585485676*$(x[1]) + -0.5391102865466948*$(x[2]) + 0.8633503800224367*$(x[3]))))))) + 0.5912184082121308*(0.8366427516313624 + 0.8654420505988725*(0.33202390613731003 + -0.8931954910636541*$(x[1]) + 0.7142724585602056*$(x[2]) + -0.28852147983722487*$(x[3]))/(1 + exp(-(0.33202390613731003 + -0.8931954910636541*$(x[1]) + 0.7142724585602056*$(x[2]) + -0.28852147983722487*$(x[3])))) + -0.07448940361379819*(-0.8935890604396688 + -0.29936605585485676*$(x[1]) + -0.5391102865466948*$(x[2]) + 0.8633503800224367*$(x[3]))/(1 + exp(-(-0.8935890604396688 + -0.29936605585485676*$(x[1]) + -0.5391102865466948*$(x[2]) + 0.8633503800224367*$(x[3])))))/(1 + exp(-(0.8366427516313624 + 0.8654420505988725*(0.33202390613731003 + -0.8931954910636541*$(x[1]) + 0.7142724585602056*$(x[2]) + -0.28852147983722487*$(x[3]))/(1 + exp(-(0.33202390613731003 + -0.8931954910636541*$(x[1]) + 0.7142724585602056*$(x[2]) + -0.28852147983722487*$(x[3])))) + -0.07448940361379819*(-0.8935890604396688 + -0.29936605585485676*$(x[1]) + -0.5391102865466948*$(x[2]) + 0.8633503800224367*$(x[3]))/(1 + exp(-(-0.8935890604396688 + -0.29936605585485676*$(x[1]) + -0.5391102865466948*$(x[2]) + 0.8633503800224367*$(x[3]))))))))/(1 + exp(-(0.8216722410540171 + 0.5667551555087149*(0.1716391672055586 + 0.7301849089692007*(0.33202390613731003 + -0.8931954910636541*$(x[1]) + 0.7142724585602056*$(x[2]) + -0.28852147983722487*$(x[3]))/(1 + exp(-(0.33202390613731003 + -0.8931954910636541*$(x[1]) + 0.7142724585602056*$(x[2]) + -0.28852147983722487*$(x[3])))) + 0.6276077641275091*(-0.8935890604396688 + -0.29936605585485676*$(x[1]) + -0.5391102865466948*$(x[2]) + 0.8633503800224367*$(x[3]))/(1 + exp(-(-0.8935890604396688 + -0.29936605585485676*$(x[1]) + -0.5391102865466948*$(x[2]) + 0.8633503800224367*$(x[3])))))/(1 + exp(-(0.1716391672055586 + 0.7301849089692007*(0.33202390613731003 + -0.8931954910636541*$(x[1]) + 0.7142724585602056*$(x[2]) + -0.28852147983722487*$(x[3]))/(1 + exp(-(0.33202390613731003 + -0.8931954910636541*$(x[1]) + 0.7142724585602056*$(x[2]) + -0.28852147983722487*$(x[3])))) + 0.6276077641275091*(-0.8935890604396688 + -0.29936605585485676*$(x[1]) + -0.5391102865466948*$(x[2]) + 0.8633503800224367*$(x[3]))/(1 + exp(-(-0.8935890604396688 + -0.29936605585485676*$(x[1]) + -0.5391102865466948*$(x[2]) + 0.8633503800224367*$(x[3]))))))) + 0.5912184082121308*(0.8366427516313624 + 0.8654420505988725*(0.33202390613731003 + -0.8931954910636541*$(x[1]) + 0.7142724585602056*$(x[2]) + -0.28852147983722487*$(x[3]))/(1 + exp(-(0.33202390613731003 + -0.8931954910636541*$(x[1]) + 0.7142724585602056*$(x[2]) + -0.28852147983722487*$(x[3])))) + -0.07448940361379819*(-0.8935890604396688 + -0.29936605585485676*$(x[1]) + -0.5391102865466948*$(x[2]) + 0.8633503800224367*$(x[3]))/(1 + exp(-(-0.8935890604396688 + -0.29936605585485676*$(x[1]) + -0.5391102865466948*$(x[2]) + 0.8633503800224367*$(x[3])))))/(1 + exp(-(0.8366427516313624 + 0.8654420505988725*(0.33202390613731003 + -0.8931954910636541*$(x[1]) + 0.7142724585602056*$(x[2]) + -0.28852147983722487*$(x[3]))/(1 + exp(-(0.33202390613731003 + -0.8931954910636541*$(x[1]) + 0.7142724585602056*$(x[2]) + -0.28852147983722487*$(x[3])))) + -0.07448940361379819*(-0.8935890604396688 + -0.29936605585485676*$(x[1]) + -0.5391102865466948*$(x[2]) + 0.8633503800224367*$(x[3]))/(1 + exp(-(-0.8935890604396688 + -0.29936605585485676*$(x[1]) + -0.5391102865466948*$(x[2]) + 0.8633503800224367*$(x[3])))))))))))/(1 + exp(-(0.758903986598098 + 0.8106379052679875*(0.47487042435595583 + 0.4488775132618512*(0.1716391672055586 + 0.7301849089692007*(0.33202390613731003 + -0.8931954910636541*$(x[1]) + 0.7142724585602056*$(x[2]) + -0.28852147983722487*$(x[3]))/(1 + exp(-(0.33202390613731003 + -0.8931954910636541*$(x[1]) + 0.7142724585602056*$(x[2]) + -0.28852147983722487*$(x[3])))) + 0.6276077641275091*(-0.8935890604396688 + -0.29936605585485676*$(x[1]) + -0.5391102865466948*$(x[2]) + 0.8633503800224367*$(x[3]))/(1 + exp(-(-0.8935890604396688 + -0.29936605585485676*$(x[1]) + -0.5391102865466948*$(x[2]) + 0.8633503800224367*$(x[3])))))/(1 + exp(-(0.1716391672055586 + 0.7301849089692007*(0.33202390613731003 + -0.8931954910636541*$(x[1]) + 0.7142724585602056*$(x[2]) + -0.28852147983722487*$(x[3]))/(1 + exp(-(0.33202390613731003 + -0.8931954910636541*$(x[1]) + 0.7142724585602056*$(x[2]) + -0.28852147983722487*$(x[3])))) + 0.6276077641275091*(-0.8935890604396688 + -0.29936605585485676*$(x[1]) + -0.5391102865466948*$(x[2]) + 0.8633503800224367*$(x[3]))/(1 + exp(-(-0.8935890604396688 + -0.29936605585485676*$(x[1]) + -0.5391102865466948*$(x[2]) + 0.8633503800224367*$(x[3]))))))) + 0.015398554931854491*(0.8366427516313624 + 0.8654420505988725*(0.33202390613731003 + -0.8931954910636541*$(x[1]) + 0.7142724585602056*$(x[2]) + -0.28852147983722487*$(x[3]))/(1 + exp(-(0.33202390613731003 + -0.8931954910636541*$(x[1]) + 0.7142724585602056*$(x[2]) + -0.28852147983722487*$(x[3])))) + -0.07448940361379819*(-0.8935890604396688 + -0.29936605585485676*$(x[1]) + -0.5391102865466948*$(x[2]) + 0.8633503800224367*$(x[3]))/(1 + exp(-(-0.8935890604396688 + -0.29936605585485676*$(x[1]) + -0.5391102865466948*$(x[2]) + 0.8633503800224367*$(x[3])))))/(1 + exp(-(0.8366427516313624 + 0.8654420505988725*(0.33202390613731003 + -0.8931954910636541*$(x[1]) + 0.7142724585602056*$(x[2]) + -0.28852147983722487*$(x[3]))/(1 + exp(-(0.33202390613731003 + -0.8931954910636541*$(x[1]) + 0.7142724585602056*$(x[2]) + -0.28852147983722487*$(x[3])))) + -0.07448940361379819*(-0.8935890604396688 + -0.29936605585485676*$(x[1]) + -0.5391102865466948*$(x[2]) + 0.8633503800224367*$(x[3]))/(1 + exp(-(-0.8935890604396688 + -0.29936605585485676*$(x[1]) + -0.5391102865466948*$(x[2]) + 0.8633503800224367*$(x[3]))))))))/(1 + exp(-(0.47487042435595583 + 0.4488775132618512*(0.1716391672055586 + 0.7301849089692007*(0.33202390613731003 + -0.8931954910636541*$(x[1]) + 0.7142724585602056*$(x[2]) + -0.28852147983722487*$(x[3]))/(1 + exp(-(0.33202390613731003 + -0.8931954910636541*$(x[1]) + 0.7142724585602056*$(x[2]) + -0.28852147983722487*$(x[3])))) + 0.6276077641275091*(-0.8935890604396688 + -0.29936605585485676*$(x[1]) + -0.5391102865466948*$(x[2]) + 0.8633503800224367*$(x[3]))/(1 + exp(-(-0.8935890604396688 + -0.29936605585485676*$(x[1]) + -0.5391102865466948*$(x[2]) + 0.8633503800224367*$(x[3])))))/(1 + exp(-(0.1716391672055586 + 0.7301849089692007*(0.33202390613731003 + -0.8931954910636541*$(x[1]) + 0.7142724585602056*$(x[2]) + -0.28852147983722487*$(x[3]))/(1 + exp(-(0.33202390613731003 + -0.8931954910636541*$(x[1]) + 0.7142724585602056*$(x[2]) + -0.28852147983722487*$(x[3])))) + 0.6276077641275091*(-0.8935890604396688 + -0.29936605585485676*$(x[1]) + -0.5391102865466948*$(x[2]) + 0.8633503800224367*$(x[3]))/(1 + exp(-(-0.8935890604396688 + -0.29936605585485676*$(x[1]) + -0.5391102865466948*$(x[2]) + 0.8633503800224367*$(x[3]))))))) + 0.015398554931854491*(0.8366427516313624 + 0.8654420505988725*(0.33202390613731003 + -0.8931954910636541*$(x[1]) + 0.7142724585602056*$(x[2]) + -0.28852147983722487*$(x[3]))/(1 + exp(-(0.33202390613731003 + -0.8931954910636541*$(x[1]) + 0.7142724585602056*$(x[2]) + -0.28852147983722487*$(x[3])))) + -0.07448940361379819*(-0.8935890604396688 + -0.29936605585485676*$(x[1]) + -0.5391102865466948*$(x[2]) + 0.8633503800224367*$(x[3]))/(1 + exp(-(-0.8935890604396688 + -0.29936605585485676*$(x[1]) + -0.5391102865466948*$(x[2]) + 0.8633503800224367*$(x[3])))))/(1 + exp(-(0.8366427516313624 + 0.8654420505988725*(0.33202390613731003 + -0.8931954910636541*$(x[1]) + 0.7142724585602056*$(x[2]) + -0.28852147983722487*$(x[3]))/(1 + exp(-(0.33202390613731003 + -0.8931954910636541*$(x[1]) + 0.7142724585602056*$(x[2]) + -0.28852147983722487*$(x[3])))) + -0.07448940361379819*(-0.8935890604396688 + -0.29936605585485676*$(x[1]) + -0.5391102865466948*$(x[2]) + 0.8633503800224367*$(x[3]))/(1 + exp(-(-0.8935890604396688 + -0.29936605585485676*$(x[1]) + -0.5391102865466948*$(x[2]) + 0.8633503800224367*$(x[3])))))))))) + -0.6668215058198093*(0.8216722410540171 + 0.5667551555087149*(0.1716391672055586 + 0.7301849089692007*(0.33202390613731003 + -0.8931954910636541*$(x[1]) + 0.7142724585602056*$(x[2]) + -0.28852147983722487*$(x[3]))/(1 + exp(-(0.33202390613731003 + -0.8931954910636541*$(x[1]) + 0.7142724585602056*$(x[2]) + -0.28852147983722487*$(x[3])))) + 0.6276077641275091*(-0.8935890604396688 + -0.29936605585485676*$(x[1]) + -0.5391102865466948*$(x[2]) + 0.8633503800224367*$(x[3]))/(1 + exp(-(-0.8935890604396688 + -0.29936605585485676*$(x[1]) + -0.5391102865466948*$(x[2]) + 0.8633503800224367*$(x[3])))))/(1 + exp(-(0.1716391672055586 + 0.7301849089692007*(0.33202390613731003 + -0.8931954910636541*$(x[1]) + 0.7142724585602056*$(x[2]) + -0.28852147983722487*$(x[3]))/(1 + exp(-(0.33202390613731003 + -0.8931954910636541*$(x[1]) + 0.7142724585602056*$(x[2]) + -0.28852147983722487*$(x[3])))) + 0.6276077641275091*(-0.8935890604396688 + -0.29936605585485676*$(x[1]) + -0.5391102865466948*$(x[2]) + 0.8633503800224367*$(x[3]))/(1 + exp(-(-0.8935890604396688 + -0.29936605585485676*$(x[1]) + -0.5391102865466948*$(x[2]) + 0.8633503800224367*$(x[3]))))))) + 0.5912184082121308*(0.8366427516313624 + 0.8654420505988725*(0.33202390613731003 + -0.8931954910636541*$(x[1]) + 0.7142724585602056*$(x[2]) + -0.28852147983722487*$(x[3]))/(1 + exp(-(0.33202390613731003 + -0.8931954910636541*$(x[1]) + 0.7142724585602056*$(x[2]) + -0.28852147983722487*$(x[3])))) + -0.07448940361379819*(-0.8935890604396688 + -0.29936605585485676*$(x[1]) + -0.5391102865466948*$(x[2]) + 0.8633503800224367*$(x[3]))/(1 + exp(-(-0.8935890604396688 + -0.29936605585485676*$(x[1]) + -0.5391102865466948*$(x[2]) + 0.8633503800224367*$(x[3])))))/(1 + exp(-(0.8366427516313624 + 0.8654420505988725*(0.33202390613731003 + -0.8931954910636541*$(x[1]) + 0.7142724585602056*$(x[2]) + -0.28852147983722487*$(x[3]))/(1 + exp(-(0.33202390613731003 + -0.8931954910636541*$(x[1]) + 0.7142724585602056*$(x[2]) + -0.28852147983722487*$(x[3])))) + -0.07448940361379819*(-0.8935890604396688 + -0.29936605585485676*$(x[1]) + -0.5391102865466948*$(x[2]) + 0.8633503800224367*$(x[3]))/(1 + exp(-(-0.8935890604396688 + -0.29936605585485676*$(x[1]) + -0.5391102865466948*$(x[2]) + 0.8633503800224367*$(x[3]))))))))/(1 + exp(-(0.8216722410540171 + 0.5667551555087149*(0.1716391672055586 + 0.7301849089692007*(0.33202390613731003 + -0.8931954910636541*$(x[1]) + 0.7142724585602056*$(x[2]) + -0.28852147983722487*$(x[3]))/(1 + exp(-(0.33202390613731003 + -0.8931954910636541*$(x[1]) + 0.7142724585602056*$(x[2]) + -0.28852147983722487*$(x[3])))) + 0.6276077641275091*(-0.8935890604396688 + -0.29936605585485676*$(x[1]) + -0.5391102865466948*$(x[2]) + 0.8633503800224367*$(x[3]))/(1 + exp(-(-0.8935890604396688 + -0.29936605585485676*$(x[1]) + -0.5391102865466948*$(x[2]) + 0.8633503800224367*$(x[3])))))/(1 + exp(-(0.1716391672055586 + 0.7301849089692007*(0.33202390613731003 + -0.8931954910636541*$(x[1]) + 0.7142724585602056*$(x[2]) + -0.28852147983722487*$(x[3]))/(1 + exp(-(0.33202390613731003 + -0.8931954910636541*$(x[1]) + 0.7142724585602056*$(x[2]) + -0.28852147983722487*$(x[3])))) + 0.6276077641275091*(-0.8935890604396688 + -0.29936605585485676*$(x[1]) + -0.5391102865466948*$(x[2]) + 0.8633503800224367*$(x[3]))/(1 + exp(-(-0.8935890604396688 + -0.29936605585485676*$(x[1]) + -0.5391102865466948*$(x[2]) + 0.8633503800224367*$(x[3]))))))) + 0.5912184082121308*(0.8366427516313624 + 0.8654420505988725*(0.33202390613731003 + -0.8931954910636541*$(x[1]) + 0.7142724585602056*$(x[2]) + -0.28852147983722487*$(x[3]))/(1 + exp(-(0.33202390613731003 + -0.8931954910636541*$(x[1]) + 0.7142724585602056*$(x[2]) + -0.28852147983722487*$(x[3])))) + -0.07448940361379819*(-0.8935890604396688 + -0.29936605585485676*$(x[1]) + -0.5391102865466948*$(x[2]) + 0.8633503800224367*$(x[3]))/(1 + exp(-(-0.8935890604396688 + -0.29936605585485676*$(x[1]) + -0.5391102865466948*$(x[2]) + 0.8633503800224367*$(x[3])))))/(1 + exp(-(0.8366427516313624 + 0.8654420505988725*(0.33202390613731003 + -0.8931954910636541*$(x[1]) + 0.7142724585602056*$(x[2]) + -0.28852147983722487*$(x[3]))/(1 + exp(-(0.33202390613731003 + -0.8931954910636541*$(x[1]) + 0.7142724585602056*$(x[2]) + -0.28852147983722487*$(x[3])))) + -0.07448940361379819*(-0.8935890604396688 + -0.29936605585485676*$(x[1]) + -0.5391102865466948*$(x[2]) + 0.8633503800224367*$(x[3]))/(1 + exp(-(-0.8935890604396688 + -0.29936605585485676*$(x[1]) + -0.5391102865466948*$(x[2]) + 0.8633503800224367*$(x[3]))))))))))))) + (-0.09143860592972564 + 0.3407854070498746*(0.47487042435595583 + 0.4488775132618512*(0.1716391672055586 + 0.7301849089692007*(0.33202390613731003 + -0.8931954910636541*$(x[1]) + 0.7142724585602056*$(x[2]) + -0.28852147983722487*$(x[3]))/(1 + exp(-(0.33202390613731003 + -0.8931954910636541*$(x[1]) + 0.7142724585602056*$(x[2]) + -0.28852147983722487*$(x[3])))) + 0.6276077641275091*(-0.8935890604396688 + -0.29936605585485676*$(x[1]) + -0.5391102865466948*$(x[2]) + 0.8633503800224367*$(x[3]))/(1 + exp(-(-0.8935890604396688 + -0.29936605585485676*$(x[1]) + -0.5391102865466948*$(x[2]) + 0.8633503800224367*$(x[3])))))/(1 + exp(-(0.1716391672055586 + 0.7301849089692007*(0.33202390613731003 + -0.8931954910636541*$(x[1]) + 0.7142724585602056*$(x[2]) + -0.28852147983722487*$(x[3]))/(1 + exp(-(0.33202390613731003 + -0.8931954910636541*$(x[1]) + 0.7142724585602056*$(x[2]) + -0.28852147983722487*$(x[3])))) + 0.6276077641275091*(-0.8935890604396688 + -0.29936605585485676*$(x[1]) + -0.5391102865466948*$(x[2]) + 0.8633503800224367*$(x[3]))/(1 + exp(-(-0.8935890604396688 + -0.29936605585485676*$(x[1]) + -0.5391102865466948*$(x[2]) + 0.8633503800224367*$(x[3]))))))) + 0.015398554931854491*(0.8366427516313624 + 0.8654420505988725*(0.33202390613731003 + -0.8931954910636541*$(x[1]) + 0.7142724585602056*$(x[2]) + -0.28852147983722487*$(x[3]))/(1 + exp(-(0.33202390613731003 + -0.8931954910636541*$(x[1]) + 0.7142724585602056*$(x[2]) + -0.28852147983722487*$(x[3])))) + -0.07448940361379819*(-0.8935890604396688 + -0.29936605585485676*$(x[1]) + -0.5391102865466948*$(x[2]) + 0.8633503800224367*$(x[3]))/(1 + exp(-(-0.8935890604396688 + -0.29936605585485676*$(x[1]) + -0.5391102865466948*$(x[2]) + 0.8633503800224367*$(x[3])))))/(1 + exp(-(0.8366427516313624 + 0.8654420505988725*(0.33202390613731003 + -0.8931954910636541*$(x[1]) + 0.7142724585602056*$(x[2]) + -0.28852147983722487*$(x[3]))/(1 + exp(-(0.33202390613731003 + -0.8931954910636541*$(x[1]) + 0.7142724585602056*$(x[2]) + -0.28852147983722487*$(x[3])))) + -0.07448940361379819*(-0.8935890604396688 + -0.29936605585485676*$(x[1]) + -0.5391102865466948*$(x[2]) + 0.8633503800224367*$(x[3]))/(1 + exp(-(-0.8935890604396688 + -0.29936605585485676*$(x[1]) + -0.5391102865466948*$(x[2]) + 0.8633503800224367*$(x[3]))))))))/(1 + exp(-(0.47487042435595583 + 0.4488775132618512*(0.1716391672055586 + 0.7301849089692007*(0.33202390613731003 + -0.8931954910636541*$(x[1]) + 0.7142724585602056*$(x[2]) + -0.28852147983722487*$(x[3]))/(1 + exp(-(0.33202390613731003 + -0.8931954910636541*$(x[1]) + 0.7142724585602056*$(x[2]) + -0.28852147983722487*$(x[3])))) + 0.6276077641275091*(-0.8935890604396688 + -0.29936605585485676*$(x[1]) + -0.5391102865466948*$(x[2]) + 0.8633503800224367*$(x[3]))/(1 + exp(-(-0.8935890604396688 + -0.29936605585485676*$(x[1]) + -0.5391102865466948*$(x[2]) + 0.8633503800224367*$(x[3])))))/(1 + exp(-(0.1716391672055586 + 0.7301849089692007*(0.33202390613731003 + -0.8931954910636541*$(x[1]) + 0.7142724585602056*$(x[2]) + -0.28852147983722487*$(x[3]))/(1 + exp(-(0.33202390613731003 + -0.8931954910636541*$(x[1]) + 0.7142724585602056*$(x[2]) + -0.28852147983722487*$(x[3])))) + 0.6276077641275091*(-0.8935890604396688 + -0.29936605585485676*$(x[1]) + -0.5391102865466948*$(x[2]) + 0.8633503800224367*$(x[3]))/(1 + exp(-(-0.8935890604396688 + -0.29936605585485676*$(x[1]) + -0.5391102865466948*$(x[2]) + 0.8633503800224367*$(x[3]))))))) + 0.015398554931854491*(0.8366427516313624 + 0.8654420505988725*(0.33202390613731003 + -0.8931954910636541*$(x[1]) + 0.7142724585602056*$(x[2]) + -0.28852147983722487*$(x[3]))/(1 + exp(-(0.33202390613731003 + -0.8931954910636541*$(x[1]) + 0.7142724585602056*$(x[2]) + -0.28852147983722487*$(x[3])))) + -0.07448940361379819*(-0.8935890604396688 + -0.29936605585485676*$(x[1]) + -0.5391102865466948*$(x[2]) + 0.8633503800224367*$(x[3]))/(1 + exp(-(-0.8935890604396688 + -0.29936605585485676*$(x[1]) + -0.5391102865466948*$(x[2]) + 0.8633503800224367*$(x[3])))))/(1 + exp(-(0.8366427516313624 + 0.8654420505988725*(0.33202390613731003 + -0.8931954910636541*$(x[1]) + 0.7142724585602056*$(x[2]) + -0.28852147983722487*$(x[3]))/(1 + exp(-(0.33202390613731003 + -0.8931954910636541*$(x[1]) + 0.7142724585602056*$(x[2]) + -0.28852147983722487*$(x[3])))) + -0.07448940361379819*(-0.8935890604396688 + -0.29936605585485676*$(x[1]) + -0.5391102865466948*$(x[2]) + 0.8633503800224367*$(x[3]))/(1 + exp(-(-0.8935890604396688 + -0.29936605585485676*$(x[1]) + -0.5391102865466948*$(x[2]) + 0.8633503800224367*$(x[3])))))))))) + 0.24612879529032217*(0.8216722410540171 + 0.5667551555087149*(0.1716391672055586 + 0.7301849089692007*(0.33202390613731003 + -0.8931954910636541*$(x[1]) + 0.7142724585602056*$(x[2]) + -0.28852147983722487*$(x[3]))/(1 + exp(-(0.33202390613731003 + -0.8931954910636541*$(x[1]) + 0.7142724585602056*$(x[2]) + -0.28852147983722487*$(x[3])))) + 0.6276077641275091*(-0.8935890604396688 + -0.29936605585485676*$(x[1]) + -0.5391102865466948*$(x[2]) + 0.8633503800224367*$(x[3]))/(1 + exp(-(-0.8935890604396688 + -0.29936605585485676*$(x[1]) + -0.5391102865466948*$(x[2]) + 0.8633503800224367*$(x[3])))))/(1 + exp(-(0.1716391672055586 + 0.7301849089692007*(0.33202390613731003 + -0.8931954910636541*$(x[1]) + 0.7142724585602056*$(x[2]) + -0.28852147983722487*$(x[3]))/(1 + exp(-(0.33202390613731003 + -0.8931954910636541*$(x[1]) + 0.7142724585602056*$(x[2]) + -0.28852147983722487*$(x[3])))) + 0.6276077641275091*(-0.8935890604396688 + -0.29936605585485676*$(x[1]) + -0.5391102865466948*$(x[2]) + 0.8633503800224367*$(x[3]))/(1 + exp(-(-0.8935890604396688 + -0.29936605585485676*$(x[1]) + -0.5391102865466948*$(x[2]) + 0.8633503800224367*$(x[3]))))))) + 0.5912184082121308*(0.8366427516313624 + 0.8654420505988725*(0.33202390613731003 + -0.8931954910636541*$(x[1]) + 0.7142724585602056*$(x[2]) + -0.28852147983722487*$(x[3]))/(1 + exp(-(0.33202390613731003 + -0.8931954910636541*$(x[1]) + 0.7142724585602056*$(x[2]) + -0.28852147983722487*$(x[3])))) + -0.07448940361379819*(-0.8935890604396688 + -0.29936605585485676*$(x[1]) + -0.5391102865466948*$(x[2]) + 0.8633503800224367*$(x[3]))/(1 + exp(-(-0.8935890604396688 + -0.29936605585485676*$(x[1]) + -0.5391102865466948*$(x[2]) + 0.8633503800224367*$(x[3])))))/(1 + exp(-(0.8366427516313624 + 0.8654420505988725*(0.33202390613731003 + -0.8931954910636541*$(x[1]) + 0.7142724585602056*$(x[2]) + -0.28852147983722487*$(x[3]))/(1 + exp(-(0.33202390613731003 + -0.8931954910636541*$(x[1]) + 0.7142724585602056*$(x[2]) + -0.28852147983722487*$(x[3])))) + -0.07448940361379819*(-0.8935890604396688 + -0.29936605585485676*$(x[1]) + -0.5391102865466948*$(x[2]) + 0.8633503800224367*$(x[3]))/(1 + exp(-(-0.8935890604396688 + -0.29936605585485676*$(x[1]) + -0.5391102865466948*$(x[2]) + 0.8633503800224367*$(x[3]))))))))/(1 + exp(-(0.8216722410540171 + 0.5667551555087149*(0.1716391672055586 + 0.7301849089692007*(0.33202390613731003 + -0.8931954910636541*$(x[1]) + 0.7142724585602056*$(x[2]) + -0.28852147983722487*$(x[3]))/(1 + exp(-(0.33202390613731003 + -0.8931954910636541*$(x[1]) + 0.7142724585602056*$(x[2]) + -0.28852147983722487*$(x[3])))) + 0.6276077641275091*(-0.8935890604396688 + -0.29936605585485676*$(x[1]) + -0.5391102865466948*$(x[2]) + 0.8633503800224367*$(x[3]))/(1 + exp(-(-0.8935890604396688 + -0.29936605585485676*$(x[1]) + -0.5391102865466948*$(x[2]) + 0.8633503800224367*$(x[3])))))/(1 + exp(-(0.1716391672055586 + 0.7301849089692007*(0.33202390613731003 + -0.8931954910636541*$(x[1]) + 0.7142724585602056*$(x[2]) + -0.28852147983722487*$(x[3]))/(1 + exp(-(0.33202390613731003 + -0.8931954910636541*$(x[1]) + 0.7142724585602056*$(x[2]) + -0.28852147983722487*$(x[3])))) + 0.6276077641275091*(-0.8935890604396688 + -0.29936605585485676*$(x[1]) + -0.5391102865466948*$(x[2]) + 0.8633503800224367*$(x[3]))/(1 + exp(-(-0.8935890604396688 + -0.29936605585485676*$(x[1]) + -0.5391102865466948*$(x[2]) + 0.8633503800224367*$(x[3]))))))) + 0.5912184082121308*(0.8366427516313624 + 0.8654420505988725*(0.33202390613731003 + -0.8931954910636541*$(x[1]) + 0.7142724585602056*$(x[2]) + -0.28852147983722487*$(x[3]))/(1 + exp(-(0.33202390613731003 + -0.8931954910636541*$(x[1]) + 0.7142724585602056*$(x[2]) + -0.28852147983722487*$(x[3])))) + -0.07448940361379819*(-0.8935890604396688 + -0.29936605585485676*$(x[1]) + -0.5391102865466948*$(x[2]) + 0.8633503800224367*$(x[3]))/(1 + exp(-(-0.8935890604396688 + -0.29936605585485676*$(x[1]) + -0.5391102865466948*$(x[2]) + 0.8633503800224367*$(x[3])))))/(1 + exp(-(0.8366427516313624 + 0.8654420505988725*(0.33202390613731003 + -0.8931954910636541*$(x[1]) + 0.7142724585602056*$(x[2]) + -0.28852147983722487*$(x[3]))/(1 + exp(-(0.33202390613731003 + -0.8931954910636541*$(x[1]) + 0.7142724585602056*$(x[2]) + -0.28852147983722487*$(x[3])))) + -0.07448940361379819*(-0.8935890604396688 + -0.29936605585485676*$(x[1]) + -0.5391102865466948*$(x[2]) + 0.8633503800224367*$(x[3]))/(1 + exp(-(-0.8935890604396688 + -0.29936605585485676*$(x[1]) + -0.5391102865466948*$(x[2]) + 0.8633503800224367*$(x[3])))))))))))/(1 + exp(-(-0.09143860592972564 + 0.3407854070498746*(0.47487042435595583 + 0.4488775132618512*(0.1716391672055586 + 0.7301849089692007*(0.33202390613731003 + -0.8931954910636541*$(x[1]) + 0.7142724585602056*$(x[2]) + -0.28852147983722487*$(x[3]))/(1 + exp(-(0.33202390613731003 + -0.8931954910636541*$(x[1]) + 0.7142724585602056*$(x[2]) + -0.28852147983722487*$(x[3])))) + 0.6276077641275091*(-0.8935890604396688 + -0.29936605585485676*$(x[1]) + -0.5391102865466948*$(x[2]) + 0.8633503800224367*$(x[3]))/(1 + exp(-(-0.8935890604396688 + -0.29936605585485676*$(x[1]) + -0.5391102865466948*$(x[2]) + 0.8633503800224367*$(x[3])))))/(1 + exp(-(0.1716391672055586 + 0.7301849089692007*(0.33202390613731003 + -0.8931954910636541*$(x[1]) + 0.7142724585602056*$(x[2]) + -0.28852147983722487*$(x[3]))/(1 + exp(-(0.33202390613731003 + -0.8931954910636541*$(x[1]) + 0.7142724585602056*$(x[2]) + -0.28852147983722487*$(x[3])))) + 0.6276077641275091*(-0.8935890604396688 + -0.29936605585485676*$(x[1]) + -0.5391102865466948*$(x[2]) + 0.8633503800224367*$(x[3]))/(1 + exp(-(-0.8935890604396688 + -0.29936605585485676*$(x[1]) + -0.5391102865466948*$(x[2]) + 0.8633503800224367*$(x[3]))))))) + 0.015398554931854491*(0.8366427516313624 + 0.8654420505988725*(0.33202390613731003 + -0.8931954910636541*$(x[1]) + 0.7142724585602056*$(x[2]) + -0.28852147983722487*$(x[3]))/(1 + exp(-(0.33202390613731003 + -0.8931954910636541*$(x[1]) + 0.7142724585602056*$(x[2]) + -0.28852147983722487*$(x[3])))) + -0.07448940361379819*(-0.8935890604396688 + -0.29936605585485676*$(x[1]) + -0.5391102865466948*$(x[2]) + 0.8633503800224367*$(x[3]))/(1 + exp(-(-0.8935890604396688 + -0.29936605585485676*$(x[1]) + -0.5391102865466948*$(x[2]) + 0.8633503800224367*$(x[3])))))/(1 + exp(-(0.8366427516313624 + 0.8654420505988725*(0.33202390613731003 + -0.8931954910636541*$(x[1]) + 0.7142724585602056*$(x[2]) + -0.28852147983722487*$(x[3]))/(1 + exp(-(0.33202390613731003 + -0.8931954910636541*$(x[1]) + 0.7142724585602056*$(x[2]) + -0.28852147983722487*$(x[3])))) + -0.07448940361379819*(-0.8935890604396688 + -0.29936605585485676*$(x[1]) + -0.5391102865466948*$(x[2]) + 0.8633503800224367*$(x[3]))/(1 + exp(-(-0.8935890604396688 + -0.29936605585485676*$(x[1]) + -0.5391102865466948*$(x[2]) + 0.8633503800224367*$(x[3]))))))))/(1 + exp(-(0.47487042435595583 + 0.4488775132618512*(0.1716391672055586 + 0.7301849089692007*(0.33202390613731003 + -0.8931954910636541*$(x[1]) + 0.7142724585602056*$(x[2]) + -0.28852147983722487*$(x[3]))/(1 + exp(-(0.33202390613731003 + -0.8931954910636541*$(x[1]) + 0.7142724585602056*$(x[2]) + -0.28852147983722487*$(x[3])))) + 0.6276077641275091*(-0.8935890604396688 + -0.29936605585485676*$(x[1]) + -0.5391102865466948*$(x[2]) + 0.8633503800224367*$(x[3]))/(1 + exp(-(-0.8935890604396688 + -0.29936605585485676*$(x[1]) + -0.5391102865466948*$(x[2]) + 0.8633503800224367*$(x[3])))))/(1 + exp(-(0.1716391672055586 + 0.7301849089692007*(0.33202390613731003 + -0.8931954910636541*$(x[1]) + 0.7142724585602056*$(x[2]) + -0.28852147983722487*$(x[3]))/(1 + exp(-(0.33202390613731003 + -0.8931954910636541*$(x[1]) + 0.7142724585602056*$(x[2]) + -0.28852147983722487*$(x[3])))) + 0.6276077641275091*(-0.8935890604396688 + -0.29936605585485676*$(x[1]) + -0.5391102865466948*$(x[2]) + 0.8633503800224367*$(x[3]))/(1 + exp(-(-0.8935890604396688 + -0.29936605585485676*$(x[1]) + -0.5391102865466948*$(x[2]) + 0.8633503800224367*$(x[3]))))))) + 0.015398554931854491*(0.8366427516313624 + 0.8654420505988725*(0.33202390613731003 + -0.8931954910636541*$(x[1]) + 0.7142724585602056*$(x[2]) + -0.28852147983722487*$(x[3]))/(1 + exp(-(0.33202390613731003 + -0.8931954910636541*$(x[1]) + 0.7142724585602056*$(x[2]) + -0.28852147983722487*$(x[3])))) + -0.07448940361379819*(-0.8935890604396688 + -0.29936605585485676*$(x[1]) + -0.5391102865466948*$(x[2]) + 0.8633503800224367*$(x[3]))/(1 + exp(-(-0.8935890604396688 + -0.29936605585485676*$(x[1]) + -0.5391102865466948*$(x[2]) + 0.8633503800224367*$(x[3])))))/(1 + exp(-(0.8366427516313624 + 0.8654420505988725*(0.33202390613731003 + -0.8931954910636541*$(x[1]) + 0.7142724585602056*$(x[2]) + -0.28852147983722487*$(x[3]))/(1 + exp(-(0.33202390613731003 + -0.8931954910636541*$(x[1]) + 0.7142724585602056*$(x[2]) + -0.28852147983722487*$(x[3])))) + -0.07448940361379819*(-0.8935890604396688 + -0.29936605585485676*$(x[1]) + -0.5391102865466948*$(x[2]) + 0.8633503800224367*$(x[3]))/(1 + exp(-(-0.8935890604396688 + -0.29936605585485676*$(x[1]) + -0.5391102865466948*$(x[2]) + 0.8633503800224367*$(x[3])))))))))) + 0.24612879529032217*(0.8216722410540171 + 0.5667551555087149*(0.1716391672055586 + 0.7301849089692007*(0.33202390613731003 + -0.8931954910636541*$(x[1]) + 0.7142724585602056*$(x[2]) + -0.28852147983722487*$(x[3]))/(1 + exp(-(0.33202390613731003 + -0.8931954910636541*$(x[1]) + 0.7142724585602056*$(x[2]) + -0.28852147983722487*$(x[3])))) + 0.6276077641275091*(-0.8935890604396688 + -0.29936605585485676*$(x[1]) + -0.5391102865466948*$(x[2]) + 0.8633503800224367*$(x[3]))/(1 + exp(-(-0.8935890604396688 + -0.29936605585485676*$(x[1]) + -0.5391102865466948*$(x[2]) + 0.8633503800224367*$(x[3])))))/(1 + exp(-(0.1716391672055586 + 0.7301849089692007*(0.33202390613731003 + -0.8931954910636541*$(x[1]) + 0.7142724585602056*$(x[2]) + -0.28852147983722487*$(x[3]))/(1 + exp(-(0.33202390613731003 + -0.8931954910636541*$(x[1]) + 0.7142724585602056*$(x[2]) + -0.28852147983722487*$(x[3])))) + 0.6276077641275091*(-0.8935890604396688 + -0.29936605585485676*$(x[1]) + -0.5391102865466948*$(x[2]) + 0.8633503800224367*$(x[3]))/(1 + exp(-(-0.8935890604396688 + -0.29936605585485676*$(x[1]) + -0.5391102865466948*$(x[2]) + 0.8633503800224367*$(x[3]))))))) + 0.5912184082121308*(0.8366427516313624 + 0.8654420505988725*(0.33202390613731003 + -0.8931954910636541*$(x[1]) + 0.7142724585602056*$(x[2]) + -0.28852147983722487*$(x[3]))/(1 + exp(-(0.33202390613731003 + -0.8931954910636541*$(x[1]) + 0.7142724585602056*$(x[2]) + -0.28852147983722487*$(x[3])))) + -0.07448940361379819*(-0.8935890604396688 + -0.29936605585485676*$(x[1]) + -0.5391102865466948*$(x[2]) + 0.8633503800224367*$(x[3]))/(1 + exp(-(-0.8935890604396688 + -0.29936605585485676*$(x[1]) + -0.5391102865466948*$(x[2]) + 0.8633503800224367*$(x[3])))))/(1 + exp(-(0.8366427516313624 + 0.8654420505988725*(0.33202390613731003 + -0.8931954910636541*$(x[1]) + 0.7142724585602056*$(x[2]) + -0.28852147983722487*$(x[3]))/(1 + exp(-(0.33202390613731003 + -0.8931954910636541*$(x[1]) + 0.7142724585602056*$(x[2]) + -0.28852147983722487*$(x[3])))) + -0.07448940361379819*(-0.8935890604396688 + -0.29936605585485676*$(x[1]) + -0.5391102865466948*$(x[2]) + 0.8633503800224367*$(x[3]))/(1 + exp(-(-0.8935890604396688 + -0.29936605585485676*$(x[1]) + -0.5391102865466948*$(x[2]) + 0.8633503800224367*$(x[3]))))))))/(1 + exp(-(0.8216722410540171 + 0.5667551555087149*(0.1716391672055586 + 0.7301849089692007*(0.33202390613731003 + -0.8931954910636541*$(x[1]) + 0.7142724585602056*$(x[2]) + -0.28852147983722487*$(x[3]))/(1 + exp(-(0.33202390613731003 + -0.8931954910636541*$(x[1]) + 0.7142724585602056*$(x[2]) + -0.28852147983722487*$(x[3])))) + 0.6276077641275091*(-0.8935890604396688 + -0.29936605585485676*$(x[1]) + -0.5391102865466948*$(x[2]) + 0.8633503800224367*$(x[3]))/(1 + exp(-(-0.8935890604396688 + -0.29936605585485676*$(x[1]) + -0.5391102865466948*$(x[2]) + 0.8633503800224367*$(x[3])))))/(1 + exp(-(0.1716391672055586 + 0.7301849089692007*(0.33202390613731003 + -0.8931954910636541*$(x[1]) + 0.7142724585602056*$(x[2]) + -0.28852147983722487*$(x[3]))/(1 + exp(-(0.33202390613731003 + -0.8931954910636541*$(x[1]) + 0.7142724585602056*$(x[2]) + -0.28852147983722487*$(x[3])))) + 0.6276077641275091*(-0.8935890604396688 + -0.29936605585485676*$(x[1]) + -0.5391102865466948*$(x[2]) + 0.8633503800224367*$(x[3]))/(1 + exp(-(-0.8935890604396688 + -0.29936605585485676*$(x[1]) + -0.5391102865466948*$(x[2]) + 0.8633503800224367*$(x[3]))))))) + 0.5912184082121308*(0.8366427516313624 + 0.8654420505988725*(0.33202390613731003 + -0.8931954910636541*$(x[1]) + 0.7142724585602056*$(x[2]) + -0.28852147983722487*$(x[3]))/(1 + exp(-(0.33202390613731003 + -0.8931954910636541*$(x[1]) + 0.7142724585602056*$(x[2]) + -0.28852147983722487*$(x[3])))) + -0.07448940361379819*(-0.8935890604396688 + -0.29936605585485676*$(x[1]) + -0.5391102865466948*$(x[2]) + 0.8633503800224367*$(x[3]))/(1 + exp(-(-0.8935890604396688 + -0.29936605585485676*$(x[1]) + -0.5391102865466948*$(x[2]) + 0.8633503800224367*$(x[3])))))/(1 + exp(-(0.8366427516313624 + 0.8654420505988725*(0.33202390613731003 + -0.8931954910636541*$(x[1]) + 0.7142724585602056*$(x[2]) + -0.28852147983722487*$(x[3]))/(1 + exp(-(0.33202390613731003 + -0.8931954910636541*$(x[1]) + 0.7142724585602056*$(x[2]) + -0.28852147983722487*$(x[3])))) + -0.07448940361379819*(-0.8935890604396688 + -0.29936605585485676*$(x[1]) + -0.5391102865466948*$(x[2]) + 0.8633503800224367*$(x[3]))/(1 + exp(-(-0.8935890604396688 + -0.29936605585485676*$(x[1]) + -0.5391102865466948*$(x[2]) + 0.8633503800224367*$(x[3]))))))))))))) - $q <= 0.0))

                     @objective(m, Min, q)

                     return m

max_stars_repo_name: PSORLab/RSActivationFunctions

max_issues_repo_name: PSORLab/RSActivationFunctions

max_forks_repo_name: PSORLab/RSActivationFunctions


text:
module TaskDispatcher

using Dates, CSV, DataFrames, FileIO
#using JLD

include("PlatformTime.jl")
include("taskEnvironment.jl")
#include("LogFileIO.jl")

export get_time, turn_on_logging, turn_off_logging

end


text:
# Example on how to load types and methods from C++ into an existing module
using Base.Test

module ExtendedTypes

using CxxWrap

wrap_module(CxxWrap._l_extended)

export ExtendedWorld, greet

end

using ExtendedTypes

w = ExtendedWorld()
@test greet(w) == "default hello"


text:
"""
Typical geodynamic simulations involve a large number of material parameters that have units that are often inconvenient to be directly used in numerical models
This package has two main features that help with this:
- Create a nondimensionalization object, which can be used to transfer dimensional to non-dimensional parameters (usually better for numerical solvers)
- Create an object in which you can specify material parameters employed in the geodynamic simulations

The material parameter object is designed to be extensible and can be passed on to the solvers, such that new creep laws or features can be readily added.
We also implement some typically used creep law parameters, together with tools to plot them versus and compare our results with those of published papers (to minimize mistakes).
"""
__precompile__()
module GeoParams

using Parameters        # helps setting default parameters in structures
using Unitful           # Units
using BibTeX            # references of creep laws
using Requires          # To only add plotting routines if Plots is loaded

export
        @u_str, uconvert, upreffered, unit, ustrip, NoUnits,  #  Units
        GeoUnit, GEO_units, SI_units, NO_units, AbstractGeoUnits,
        Nondimensionalize, Nondimensionalize!, Dimensionalize, Dimensionalize!,
        superscript, upreferred, GEO, SI, NONE, isDimensional, Value, NumValue, Unit,
        km, m, cm, mm, μm, Myrs, yr, s, MPa, Pa, kbar, Pas, K, C, g, kg, mol, J, kJ, Watt, μW

#
abstract type AbstractMaterialParam end                                    # structure that holds material parmeters (density, elasticity, viscosity)
abstract type AbstractMaterialParamsStruct end                             # will hold all info for a phase
abstract type AbstractPhaseDiagramsStruct <:  AbstractMaterialParam end    # will hold all info for phase diagrams
function PerpleX_LaMEM_Diagram end          # necessary as we already use this function in Units, but only define it later in PhaseDiagrams

export AbstractMaterialParam, AbstractMaterialParamsStruct, AbstractPhaseDiagramsStruct

# note that this throws a "Method definition warning regarding superscript"; that is expected & safe
#  as we add a nicer way to create output of superscripts. I have been unable to get rid of this warning,
#  as I am indeed redefining a method originally defined in Unitful
include("Units.jl")
using .Units

# Define Material Parameter structure
include("MaterialParameters.jl")
using  .MaterialParameters
export MaterialParams, SetMaterialParams

# Phase Diagrams
using  .MaterialParameters.PhaseDiagrams
export PhaseDiagram_LookupTable, PerpleX_LaMEM_Diagram

# Creep laws
using  .MaterialParameters.CreepLaw
export  ComputeCreepLaw_EpsII, ComputeCreepLaw_TauII, CreepLawVariables,
        LinearViscous, PowerlawViscous,
        DislocationCreep, SetDislocationCreep

# Density
using  .MaterialParameters.Density
export  ComputeDensity,                                # computational routines
        ComputeDensity!,
        ConstantDensity,
        PT_Density,
        PhaseDiagram_LookupTable, Read_LaMEM_Perple_X_Diagram

# Gravitational Acceleration
using  .MaterialParameters.GravitationalAcceleration
export  ComputeGravity,                                # computational routines
        ConstantGravity

# Energy parameters: Heat Capacity, Thermal conductivity, latent heat, radioactive heat
using .MaterialParameters.HeatCapacity
export  ComputeHeatCapacity,
        ComputeHeatCapacity!,
        ConstantHeatCapacity,
        T_HeatCapacity_Whittacker

using .MaterialParameters.Conductivity
export  ComputeConductivity,
        ComputeConductivity!,
        ConstantConductivity,
        T_Conductivity_Whittacker,
        TP_Conductivity,
        Set_TP_Conductivity

using .MaterialParameters.LatentHeat
export  ComputeLatentHeat,
        ConstantLatentHeat

using .MaterialParameters.RadioactiveHeat
export  ComputeRadioactiveHeat,
        ConstantRadioactiveHeat

using .MaterialParameters.Shearheating
export  ComputeShearheating, ComputeShearheating!,
        ConstantShearheating

# Seismic velocities
using .MaterialParameters.SeismicVelocity
export  ComputePwaveVelocity,  ComputeSwaveVelocity,
        ComputePwaveVelocity!, ComputeSwaveVelocity!,
        ConstantSeismicVelocity

# Add melting parameterizations
include("./MeltFraction/MeltingParameterization.jl")
using .MeltingParam
export  ComputeMeltingParam, ComputeMeltingParam!,       # calculation routines
        MeltingParam_Caricchi

# Add plotting routines - only activated if the "Plots.jl" package is loaded
function __init__()
        @require Plots = "91a5bcdd-55d7-5caf-9e0b-520d859cae80" begin
                print("Adding plotting routines of GeoParam")
                @eval include("./Plotting.jl")
        end
end

end # module


text:
# TODO - update me with real tests
@test 1 == 1


text:
futhark_mapping =
                Dict(
                     "fehu"     => "\u16a0",
                     "uruz"     => "\u16a2",
                     "thurisaz" => "\u16a6",
                     "raido"    => "\u16b1",
                     "ansus"    => "\u16ab",
                     "kenaz"    => "\u16b2",
                     "gebo"     => "\u16b7",
                     "wunjo"    => "\u16b9",

                     "hagalaz"  => "\u16ba",
                     "naudiz"   => "\u16be",
                     "isaz"     => "\u16c1",
                     "jera"     => "\u16c3",
                     "eoh"      => "\u16c7",
                     "peorth"   => "\u16c8",
                     "algiz"    => "\u16c9",
                     "sowilo"   => "\u16ca",

                     "tewaz"    => "\u16cf",
                     "berkana"  => "\u16d2",
                     "ewaz"     => "\u16d6",
                     "mannaz"   => "\u16d7",
                     "laguz"    => "\u16da",
                     "ingwaz"   => "\u16dc",
                     "othal"    => "\u16df",
                     "dagaz"    => "\u16de",
                    )

max_stars_repo_name: LCRERGO/futhark-test

max_issues_repo_name: LCRERGO/futhark-test

max_forks_repo_name: LCRERGO/futhark-test


text:
using BenchmarkTools

function calc_pi_by_gcd(N)
    s = 0
    for a in 1:N
        for b in 1:N
            s += ifelse(gcd(a,b)==1, 1, 0)
        end
        s
    end
    println(sqrt(6N^2/s))
end

function main()
    @time calc_pi_by_gcd(10000)
end

main()

max_stars_repo_name: terasakisatoshi/nimProgram

max_issues_repo_name: terasakisatoshi/nimProgram

max_forks_repo_name: terasakisatoshi/nimProgram


text:
function simulate(canvas::Canvas,nodes,seconds::Int,delta::Float64)
	time = DateTime(0)
	finish_time = time + Dates.Second(seconds)
	event_writer = EventWriter("log.log")
	# Start simulation
	while time < finish_time
		for node in nodes
			update_seen(node,canvas,event_writer,time)
		end
		for node in nodes
			move(node,canvas,0.5,0.5,delta)
		end
		reset_nodes(nodes)
		time += Dates.Second(delta)
	end
	close_writer(event_writer)
end

function reset_nodes(nodes)
	for node in nodes
		node.node_seen = Set()
	end
end


text:
function _show_dimname(io, dim::Dim)
    color = _dimcolor(io)
    printstyled(io, "Dim{"; color=color)
    printstyled(io, string(":", name(dim)); color=:yellow)
    printstyled(io, "}"; color=color)
end
function _show_dimname(io, dim::Dimension)
    printstyled(io, DD.dim2key(dim); color = _dimcolor(io))
end

function Base.show(io::IO, mime::MIME"text/plain", stack::AbstractGeoStack)
    nlayers = length(keys(stack))
    layers_str = nlayers == 1 ? "layer" : "layers"
    printstyled(io, nameof(typeof(stack)), color=:blue)
    print(io, " with $nlayers $(childtype(stack)) $layers_str:\n")
    for var in keys(stack)
        printstyled(io, "  :$var", color=:yellow)

        field_dims = dims(stack, var)
        n_dims = length(field_dims)
        dims_str = n_dims == 1 ? "dim" : "dims"
        print(io, " with $dims_str: ")
        if n_dims > 0
            for (d, dim) in enumerate(field_dims)
                _show_dimname(io, dim)
                d != length(field_dims) && print(io, ", ")
            end
            print(io, " (")
            for (d, dim) in enumerate(field_dims)
                print(io, "$(length(dim))")
                d != length(field_dims) && print(io, '×')
            end
            print(io, ')')
        end
        print(io, '\n')
    end

    if stack isa DiskGeoStack
        if filename(stack) isa AbstractString
            println(io, "\n" * filename(stack))
        else
            for (key, fn) in pairs(filename(stack))
                print(io, "\n ")
                printstyled(io, " :$key", color=:yellow)
                print(io, " = ", fn)
            end
        end
    end

    n_windows = length(window(stack))
    if n_windows > 0
        print(io, "with window:\n")
        for dim in window(stack)
            print(io, ' ')
            show(IOContext(io; :compact=>true), mime, dim)
            print(io, '\n')
        end
    end

    md = metadata(stack)
    if !(md isa NoMetadata)
        n_metadata = length(md)
        if n_metadata > 0
            print(io, "\nwith ")
            show(io, mime, md)
        end
    end
end

# Stack types can be enourmous. Just use nameof(T)
function Base.summary(io::IO, ser::AbstractGeoSeries{T,N}) where {T,N}
    if N == 0
        print(io, "0-dimensional ")
    elseif N == 1
        print(io, size(ser, 1), "-element ")
    else
        print(io, join(size(ser), "×"), " ")
    end
    printstyled(io, string(nameof(typeof(ser)), "{$(nameof(T)),$N}"); color=:blue)
    return nothing
end

function Base.show(io::IO, mime::MIME"text/plain", A::AbstractGeoSeries{T,N}) where {T,N}
    summary(io, A)
    # TODO: these need a proper interface in DD
    _printname(io, name(A))
    _printdims(io, mime, dims(A))
    !(isempty(dims(A)) || isempty(refdims(A))) && println(io)
    _printrefdims(io, mime, refdims(A))
    return nothing
end

# Move to proper interface in DD
function _printname(io::IO, name)
    if !(name == Symbol("") || name isa NoName)
        printstyled(io, string(" :", name); color=:yellow)
    end
end
function _printdims(io::IO, mime, dims::Tuple)
    if isempty(dims)
        print(io, ": ")
        return 0
    end
    printstyled(io, " with dimensions: "; color=:light_black)
    return _layout_dims(io, mime, dims)
end
function _printrefdims(io::IO, mime, refdims::Tuple)
    if isempty(refdims)
        return 0
    end
    printstyled(io, "and reference dimensions: "; color=:light_black)
    ctx = IOContext(io, :is_ref_dim=>true, :show_dim_val=>true)
    lines = _layout_dims(ctx, mime, refdims)
    return lines
end
function _layout_dims(io, mime, dims::Tuple)
    length(dims) > 0 || return 0
    ctx = IOContext(io, :compact=>true)
    if all(m -> m isa NoIndex, mode(dims))
        for d in dims[1:end-1]
            show(ctx, mime, d)
            print(io, ", ")
        end
        show(ctx, mime, dims[end])
        return 0
    else # Dims get a line each
        lines = 3
        print(io, "\n  ")
        for d in dims[1:end-1]
            show(ctx, mime, d)
            print(io, ",")
            lines += 2 # Often they wrap
            print(io, "\n  ")
        end
        show(ctx, mime, dims[end])
        return lines
    end
end

_dimcolor(io) = get(io, :is_ref_dim, false) ? :magenta : :red

function Base.show(io::IO, mime::MIME"text/plain", mode::AbstractProjected)
    DD.show(io, mime, Sampled(mode.order, mode.span, mode.sampling))
    if !(crs(mode) isa Nothing)
        print(io, " crs: ", nameof(typeof(crs(mode))))
    end
    if !(mappedcrs(mode) isa Nothing)
        print(io, " mappedcrs: ", nameof(typeof(mappedcrs(mode))))
    end
    return nothing
end


text:
# Tests of this file not covered in other tests
@testset "dual_model_variables.jl" begin
    @testset "push_to_dual_obj_aff_terms!" begin
        primal_model = soc1_test()
        dual_obj_affine_terms = Dict{VI,Float64}()
        list = MOI.get(
            primal_model,
            MOI.ListOfConstraintIndices{VVF,MOI.SecondOrderCone}(),
        )
        ci = first(list)
        func = MOI.get(primal_model, MOI.ConstraintFunction(), ci)
        set = MOI.get(primal_model, MOI.ConstraintSet(), ci)
        Dualization.push_to_dual_obj_aff_terms!(
            primal_model,
            dual_obj_affine_terms,
            VI(1),
            func,
            set,
            1,
        )
        @test isempty(dual_obj_affine_terms)
    end

    @testset "set_dual_variable_name" begin
        primal_model = soc1_test()
        vi = VI(1)
        Dualization.set_dual_variable_name(primal_model, vi, 1, "con", "")
        @test MOI.get(primal_model, MOI.VariableName(), vi) == "con_1"
        Dualization.set_dual_variable_name(primal_model, vi, 2, "con", "")
        @test MOI.get(primal_model, MOI.VariableName(), vi) == "con_2"
        Dualization.set_dual_variable_name(primal_model, vi, 2, "con", "oi")
        @test MOI.get(primal_model, MOI.VariableName(), vi) == "oicon_2"
    end
end


text:
using HypothesisTests, Distributions, Test, Random
using HypothesisTests: default_tail
using StableRNGs

@testset "Anderson-Darling" begin
@testset "One sample test" begin
    n = 1000
    rng = StableRNG(1984948)

    d = Normal(1000, 100)
    x = rand(rng, d, n)
    t = OneSampleADTest(x, d)
    @test t.A² ≈ 1.2960 atol=0.1^4
    @test pvalue(t) ≈ 0.2336 atol=0.1^4
    @test default_tail(t) == :right

    d = DoubleExponential()
    x = rand(rng, d, n)
    t = OneSampleADTest(x, Normal(mean(d), std(d)))
    @test t.A² ≈ 11.0704 atol=0.1^4
    @test pvalue(t) ≈ 0.0 atol=0.1^4
    t = OneSampleADTest(x, d)
    @test t.A² ≈ 0.8968 atol=0.1^4
    @test pvalue(t) ≈ 0.4162 atol=0.1^4

    d = Cauchy()
    x = rand(rng, Cauchy(), n)
    t = OneSampleADTest(x, Normal())
    @test pvalue(t) ≈ 0.0 atol=0.1^4
    t = OneSampleADTest(x, d)
    @test pvalue(t) ≈ 0.9640 atol=0.1^4

    d = LogNormal()
    x = rand(rng, d, n)
    t = OneSampleADTest(x, Normal(mean(d), std(d)))
    @test pvalue(t) ≈ 0.0 atol=0.1^4
    t = OneSampleADTest(x, d)
    @test pvalue(t) ≈ 0.9123 atol=0.1^4

    d = Uniform(-pi, 2pi)
    x = rand(rng, d, n)
    t = OneSampleADTest(x, d)
    @test pvalue(t) ≈ 0.2337 atol=0.1^4

    x = rand(rng, Uniform(0, 1.8), n)
    t = OneSampleADTest(x, Uniform())
    @test pvalue(t) ≈ 0.0 atol=0.1^4

    x = rand(rng, Exponential(), n)
    t = OneSampleADTest(x, Exponential())
    @test pvalue(t) ≈ 0.8579 atol=0.1^4
end

@testset "k-sample test" begin
    samples = Any[
        [38.7, 41.5, 43.8, 44.5, 45.5, 46.0, 47.7, 58.0],
        [39.2, 39.3, 39.7, 41.4, 41.8, 42.9, 43.3, 45.8],
        [34.0, 35.0, 39.0, 40.0, 43.0, 43.0, 44.0, 45.0],
        [34.0, 34.8, 34.8, 35.4, 37.2, 37.8, 41.2, 42.8]
    ]

    t = KSampleADTest(samples...)
    @test t.A²k ≈ 8.3926 atol=0.1^4
    @test t.σ ≈ 1.2038 atol=0.1^4
    @test pvalue(t) ≈ 0.0022 atol=0.1^4
    @test default_tail(t) == :right

    ts = KSampleADTest(samples..., nsim = 20000);
    @test pvalue(ts) ≈ 0.00155 atol=0.1^3

    t = KSampleADTest(samples..., modified = false)
    @test t.A²k ≈ 8.3559 atol=0.1^4
    @test t.σ ≈ 1.2038 atol=0.1^4
    @test pvalue(t) ≈ 0.0023 atol=0.1^4

    ts = KSampleADTest(samples..., modified = false, nsim = 20000);
    @test pvalue(ts) ≈ 0.00150 atol=0.1^3
end

@testset "more tests" begin
    rng =  StableRNG(31412455)
    samples = Any[rand(rng, Normal(), 50), rand(rng, Normal(0.5), 30)]
    t = KSampleADTest(samples...)
    @test pvalue(t) < 0.05

    samples = Any[rand(rng, Normal(), 50), rand(rng, Normal(), 30), rand(rng, Normal(), 20)]
    t = KSampleADTest(samples...)
    @test pvalue(t) > 0.05

    @test pvalue(OneSampleADTest(vcat(rand(rng, Normal(),500), rand(rng, Beta(2,2),500)), Beta(2,2))) ≈ 0.0 atol=0.1^4

    n = 1000
    x = rand(rng, Exponential(), n)
    @test pvalue(KSampleADTest(rand(rng, 1000), randn(rng, 1000))) ≈ 0.0 atol=eps()
    @test pvalue(KSampleADTest(x,x,x,x,x,x)) ≈ 1.0
end

end


text:
## (a kind of) forward declaration of some types to be used later

abstract type AbstractOp end
abstract type AbstractDevice end


text:
module InteractionNetworkModels

using Distributed

# Alises for referring to Paths/Interaction Sequences/Samples of Interaction Sequences (purely for readability)
include("aliases.jl")

# Types
include("Types/PathDistributions.jl")
include("Types/MarkovModels.jl")
include("Types/distributions.jl")
include("Types/hollywood_model.jl")

# Data Processing
# include("Data Processing/EdgeCounts.jl")
include("Data Processing/VertexCounts.jl")
include("Data Processing/PathSequences.jl")
include("Data Processing/Multigraphs.jl")
include("Data Processing/string_to_int.jl")
include("Data Processing/high_order_heuristic.jl")
include("Data Processing/remove_repeats.jl")
include("Data Processing/aggregate_graph.jl")

# Metric Models
# ===============

# Model types and utils
# ---------------------
include("Metric Models/SPF.jl")
include("Metric Models/SIS.jl")
include("Metric Models/SIM.jl")
include("Metric Models/utils.jl")

# Model sampling
# ---------------
# Types
include("Metric Models/Model Sampling/Types/initalisers.jl")
include("Metric Models/Model Sampling/Types/SIM_samplers.jl")
include("Metric Models/Model Sampling/Types/SIS_samplers.jl")
include("Metric Models/Model Sampling/Types/SPF_samplers.jl")
include("Metric Models/Model Sampling/Types/outputs.jl")
# SIS
include("Metric Models/Model Sampling/SIS/SIS_sampler.jl")
include("Metric Models/Model Sampling/SIS/SIS_centered_simple.jl")
include("Metric Models/Model Sampling/SIS/SIS_gibbs.jl")
include("Metric Models/Model Sampling/SIS/split_merge/SIS_split_merge_helpers.jl")
include("Metric Models/Model Sampling/SIS/split_merge/SIS_split_merge.jl")
# SIM
include("Metric Models/Model Sampling/SIM/SIM_sampler.jl")
include("Metric Models/Model Sampling/SIM/SIM_subpath.jl")
include("Metric Models/Model Sampling/SIM/SIM_gibbs.jl")
include("Metric Models/Model Sampling/SIM/SIM_length_centered.jl")
include("Metric Models/Model Sampling/SIM/SIM_proportional.jl")
# SPF
include("Metric Models/Model Sampling/SPF/SPF_sampler.jl")
include("Metric Models/Model Sampling/SPF/SPF_dc_sampler.jl")
# Summaries
include("Metric Models/Model Sampling/Summaries/plot_recipes.jl")
include("Metric Models/Model Sampling/Summaries/misc_summaries.jl")

# Posterior Sampling
# ------------------
# Types
include("Metric Models/Posterior Sampling/Types/SIM_samplers.jl")
include("Metric Models/Posterior Sampling/Types/SIS_samplers.jl")
include("Metric Models/Posterior Sampling/Types/SPF_samplers.jl")
include("Metric Models/Posterior Sampling/Types/outputs.jl")
include("Metric Models/Posterior Sampling/Types/predictives.jl")
# Sampler files
include("Metric Models/Posterior Sampling/auxiliary_terms_eval.jl")
include("Metric Models/Posterior Sampling/cooccurrence_matrices.jl")
include("Metric Models/Posterior Sampling/informed_insertion_distribution.jl")
include("Metric Models/Posterior Sampling/iex_SIM.jl")
include("Metric Models/Posterior Sampling/iex_SIM_split_merge.jl")
include("Metric Models/Posterior Sampling/iex_SIM_proportional.jl")
include("Metric Models/Posterior Sampling/iex_SIM_dependent.jl")
include("Metric Models/Posterior Sampling/iex_SIM_with_kick.jl")
include("Metric Models/Posterior Sampling/iex_SIS.jl")
include("Metric Models/Posterior Sampling/iex_SPF.jl")
# Summaries
include("Metric Models/Posterior Sampling/Summaries/plot_recipes.jl")
include("Metric Models/Posterior Sampling/Summaries/misc_summaries.jl")
include("Metric Models/Posterior Sampling/Summaries/predictive_summaries.jl")

# iMCMC Moves (new structure)
include("Metric Models/iMCMC Moves/imcmc_move_type.jl")
include("Metric Models/iMCMC Moves/edit_allocation_move.jl")
include("Metric Models/iMCMC Moves/permutation_move.jl")
include("Metric Models/iMCMC Moves/insert_delete_move.jl")
include("Metric Models/iMCMC Moves/split_merge_move.jl")
include("Metric Models/iMCMC Moves/mixture_move.jl")
include("Metric Models/Samplers/model_sampler.jl")
include("Metric Models/Samplers/posterior_sampler.jl")

# Graphs Models
# =============
include("Graph Models/utils.jl")
include("Graph Models/CER/CER.jl")
include("Graph Models/CER/CER_posterior.jl")

include("Graph Models/SNF/SNF.jl")
include("Graph Models/SNF/MCMC Moves/move_type.jl")
include("Graph Models/SNF/MCMC Moves/gibbs_moves.jl")
# include("Graph Models/SNF/SNF_samplers.jl")
# include("Graph Models/SNF/SNF_multigraph.jl")
# include("Graph Models/SNF/SNF_multigraph_gibbs.jl")
include("Graph Models/SNF/Samplers/SNF_model_sampler.jl")
include("Graph Models/SNF/Samplers/SNF_posterior_sampler.jl")
# include("Graph Models/SNF/SNF_multigraph_gibbs_posterior.jl")

end


text:
# generic functions for distribution fitting

function suffstats(dt::Type{D}, xs...) where D<:Distribution
    argtypes = tuple(D, map(typeof, xs)...)
    error("suffstats is not implemented for $argtypes.")
end

"""
    fit_mle(D, x)

Fit a distribution of type `D` to a given data set `x`.

- For univariate distribution, x can be an array of arbitrary size.
- For multivariate distribution, x should be a matrix, where each column is a sample.
"""
fit_mle(D, x)

"""
    fit_mle(D, x, w)

Fit a distribution of type `D` to a weighted data set `x`, with weights given by `w`.

Here, `w` should be an array with length `n`, where `n` is the number of samples contained in `x`.
"""
fit_mle(D, x, w)

fit_mle(dt::Type{D}, x::AbstractArray) where {D<:UnivariateDistribution} = fit_mle(D, suffstats(D, x))
fit_mle(dt::Type{D}, x::AbstractArray, w::AbstractArray) where {D<:UnivariateDistribution} = fit_mle(D, suffstats(D, x, w))

fit_mle(dt::Type{D}, x::AbstractMatrix) where {D<:MultivariateDistribution} = fit_mle(D, suffstats(D, x))
fit_mle(dt::Type{D}, x::AbstractMatrix, w::AbstractArray) where {D<:MultivariateDistribution} = fit_mle(D, suffstats(D, x, w))

fit(dt::Type{D}, x) where {D<:Distribution} = fit_mle(D, x)
fit(dt::Type{D}, args...) where {D<:Distribution} = fit_mle(D, args...)


text:
module Attrs

export @literalattrs, @defattrs, Attr, getattr, setattr!, attrnames, literal_getattr, literal_setattr!

include("interface.jl")
include("macros.jl")

end # module


text:
module TinyG

using JSON,
      SerialPorts

const versions = Dict("master" => "440.18",
                      "edge" => "442.04")

abstract AbstractTinyGDevice

type SerialTinyGDevice <: AbstractTinyGDevice
    serial::SerialPort
end

write(s::SerialTinyGDevice, m) = write(s.serial, m)

function bootloader()

end

function init(s::SerialTinyGDevice)

end

@doc """
Download the latest release versions of TinyG firmware. This will get all
available branches, currently "master" and "edge".
"""
function download_firmware()
    for k in keys(versions)
        download_firmware(k)
    end
end

@doc """
Download the latest release versions for the specified branch.
"""
function download_firmware(v::String)
    m = Pkg.dir("TinyG","deps","firmware",v)
    if !isdir(m)
        mkpath(m)
    end
    hex = "tinyg-$v-$(versions[v]).hex"
    url = "http://synthetos.github.io/binaries/$hex"
    download(url, joinpath(m,hex))
end

end # module


text:
# Author: Lukasz Bratos
include("methods.jl")

# Dane do zadania: funkcja, jej pochodna, delta, epsilon oraz maxit
f(x) = sin(x) - (x / 2) ^ 2
pf(x) = cos(x) - (x / 2)
delta = 10 ^ -5 / 2
epsilon = 10 ^ -5 / 2
maxit = 100

println("Metoda bisekcji: ", Methods.mbisekcji(f, 1.5, 2.0, delta, epsilon))
println("Metoda Newtona: ", Methods.mstycznych(f, pf, 1.5, delta, epsilon, maxit))
println("Metoda siecznych: ", Methods.msiecznych(f, 1.0, 2.0, delta, epsilon, maxit))


text:
include("Token.jl")
include("Errors.jl")

const table = Dict("int"=>INT_NUMBER, "real"=>FLOAT_NUMBER, "char"=>CHAR, "texto"=>STRING, "boleano"=>BOOL)
const map_por_to_julia = Dict("int"=>Int64, "real"=>Float64, "boleano"=>Bool)
const map_julia_to_por = Dict(Int64=>"int", Float64=>"real", Bool=>"boleano")

iscolon(t::Token)   = t.id==PUNCTUATION && t.text==":"
iscoma(t::Token)    = t.id==PUNCTUATION && t.text==","
isperiod(t::Token)  = t.id==PUNCTUATION && t.text==";"
isassign(t::Token)  = t.id==ASSIGN && t.text==":="
isliteral(t::Token) = t.id==INT_NUMBER || t.id==FLOAT_NUMBER || t.id==CHAR || t.id==STRING || t.id==BOOL
isnumber(t::Token, env)  = (table[env[t.text].type] == INT_NUMBER) || (table[env[t.text].type] == FLOAT_NUMBER) || (table[env[t.text].type] == BOOL)

type_match(t::Token, lit::Token, env) = table[env[t.text].type] == lit.id
isop(t::Token) = t.id == OPERATOR || (t.text == ")" || t.text == "(")

mutable struct var_state
    name   :: String
    init   :: Bool
    type   :: String # can be: 'int', 'real', 'char', 'texto', 'boleano'
    value  :: String
    function var_state(name, init=false, type="", value="")
        new(name, init, type, value)
    end
end

type(env, t)  = env[t.text].type
value(env, t) = env[t.text].value
init(env, t)  = env[t.text].init

type!(env, t, v)  = env[t.text].type = v
value!(env, t, v) = env[t.text].value = v
init!(env, t, v)  = env[t.text].init = v

function syntactic_parse(tokens::Tokens)::Dict
    env = Dict()

    t = next!(tokens)
    if t.id == RESERVED_WORD && t.text == "programa"
        t = next!(tokens)
        if t.id == IDENTIFIER
            bloco!(tokens, env, ["fimprog"])

        else
            error("Parsing Error - Expecting name of program.",t)
        end
    else
        error("Parsing Error - Expecting PROGRAMA.",t)
    end

    t = next!(tokens)

    if t.id != EOF
        error("Program finished but file has content.",t)
    end
    reset!(tokens) # reset counter of token
    return env
end

function declare!(tokens::Tokens, env)
    t = next!(tokens)
    current_declared_vars::Array{var_state} = []

    while t.id == IDENTIFIER || iscoma(t)
        if t.id == IDENTIFIER
            if haskey(env, t.text)
                error("Already defined variable.", t)
            end
            push!(current_declared_vars, var_state(t.text))
        end

        t = next!(tokens)
    end

    if t.id == RESERVED_WORD || t.id == CFLUX
        error("Reserved words can't be used as variable names `$(t.text)`.", t)
    end

    if iscolon(t)
        t = next!(tokens)
        if t.id == TYPE
            map(x->x.type=t.text, current_declared_vars)
        else
            error("`$(t.text)` is not a correct TYPE.", t)
        end

        t = next!(tokens)
        if isperiod(t)
            # Returned with success
            for state in current_declared_vars
                env[state.name] = state
            end
            return

        else
            error("`$(t.text)` Not an end of line.", t)
        end
    else
        error("Not correct DECLARE stmt.", t)
    end
end

function bloco!(tokens::Tokens, env, expected_end)
    t = next!(tokens)

    if t.id==RESERVED_WORD && t.text=="declare"
        declare!(tokens, env)

    elseif t.id==RESERVED_WORD && (t.text=="leia" || t.text=="escreva")
        cmd_io!(tokens, env, t.text)

    elseif t.id==IDENTIFIER
        cmd_attr!(tokens, env)

    elseif t.id==CFLUX
        control_flux_parser!(tokens, env)
    end

    if !any(x->x==t.text, expected_end)
        bloco!(tokens, env, expected_end)
    end
end

function cmd_io!(tokens::Tokens, env, io)
    t = next!(tokens)
    if t.id==PUNCTUATION && t.text=="("
        t = next!(tokens)
        if t.id==IDENTIFIER || t.id==STRING
            if t.id==STRING || haskey(env, t.text)
                if io == "leia"
                    if t.id==STRING error("String in 'leia' statement is not allowed", t) end
                    init!(env, t, true)
                else # escreva
                    if t.id!=STRING && !init(env, t)
                        error("Trying to print uninitialized variable `$(t.text)`", t)
                    end
                end # io
            elseif t.id!=STRING
                error("Trying to read from undeclared variable `$(t.text)`.", t)
            end # env

        else # id
            error("Values inside `$io` command must be a variable, not `$(t.text)`.", t)
        end # id
        t = next!(tokens)
        if t.id!=PUNCTUATION && t.text==")"
            error("Missing closing parenthesis in `$io` stmt.", t)
        end # )

        t = next!(tokens)
        if !isperiod(t) error("Missing semicolon.", t) end
    else # (
        error("Missing open parenthesis in `$io` stmt.", t)
    end # (
end

function cmd_attr!(tokens::Tokens, env)
    # var := literal | expressão
    variable = current(tokens)

    if haskey(env, variable.text)
        t = next!(tokens)
        if isassign(t)
            t = next!(tokens)
            if isliteral(t) && !isop(next(tokens))
                if type_match(variable,t, env)
                    value!(env, variable, t.text)
                    init!(env, variable, true)
                else # not compatible types
                    error("Mismatching types between `$(variable.text)` and literal of type `$(t.id)`.", t)
                end #type_match
            else # should be expr
                a_value, a_type = par_expr!(tokens, env, variable)
                value!(env, variable, string(a_value))
                init!(env, variable, true)
            end # if is literal

            t = next!(tokens)
            if !isperiod(t) error("Missing semicolon.", t) end
        else # isn't assign symbol
            # error("Assign symbol required.", t)
        end #isassing

    else #not has key
        error("Undefined variable `$(variable.text)`.", variable)
    end # haskey
end

function par_expr!(tokens::Tokens, env, expecting=nothing)
    expr = expr_to_text(tokens, env)

    expected_type = typeof(expecting)==Token ? type(env, expecting) : expecting

    if expr == ""
        roll_back(tokens)
        return "", expected_type
    end

    eval_value = nothing
    could_be_eval = false
    try
        eval_value = Meta.parse(expr)
        try
            eval_value = eval(eval_value)
            could_be_eval = true
        catch
            eval_value = expr
        end
    catch
        error("Failed to eval expression.", current(tokens))
    end

    if typeof(eval_value) <: Number && abs(eval_value) == Inf error("Division by zero is not allowed.", previous(tokens)) end

    atype = ""
    try
        if could_be_eval
            eval_value = map_por_to_julia[expected_type](eval_value)
            atype = map_julia_to_por[typeof(eval_value)]
        end
    catch
        atype = map_julia_to_por[typeof(eval_value)]
        error("Trying to cast an expression with incompatible types: `$expected_type` with `$atype`.", expecting)
    end

    roll_back(tokens)
    return eval_value, atype
end

function expr_to_text(tokens::Tokens, env)
    t = current(tokens)
    expr = ""
    l = t.line

    while true
        if t.line != l
            roll_back(tokens)
            break
        end
        if isperiod(t) break end

        if t.id==CFLUX || t.id==TYPE || t.id==RESERVED_WORD
            error("Reserved words cant be used in expressions statements.", t)
        elseif t.id==ASSIGN
            error("Assign sinal in expression. Equal is `==`.", t)
        end

        val = t.text
        if t.id == IDENTIFIER
            if !haskey(env, t.text)
                error("Using undefined variable `$(t.text)`.", t)
            else # haskey
                if !isnumber(t, env)
                    error("Trying to use non numeric or logic values in expression.", t)
                end #isnumber
                if !init(env, t)
                    error("Trying to use non uninitialized variable `$(t.text)`.", t)
                end #init
                if value(env, t) != ""
                    val = value(env, t)
                end
            end #haskey
        end #if IDENTIFIER

        if val == "V" val = "true"
        elseif val == "F" val = "false"
        end

        expr *= val
        t = next!(tokens)
    end # while

    return expr
end

function control_flux_parser!(tokens, env)
    t = current(tokens)
    if t.text == "se"
        parse_se!(tokens, env)
    elseif t.text == "enquanto"
        parse_enquanto!(tokens, env)
    elseif t.text == "faca"
        parse_faca!(tokens, env)
    end
end

function parse_se!(tokens, env)
    next!(tokens)
    par_expr!(tokens, env, "boleano")
    t = next!(tokens)

    bloco!(tokens, env, ["fimse", "senao"])

    if current(tokens).text == "senao"
        bloco!(tokens, env, ["fimse"])
    end
end

function parse_enquanto!(tokens, env)
    next!(tokens)
    par_expr!(tokens, env, "boleano")
    t = next!(tokens)
    bloco!(tokens, env, ["fimenq"])
end

function parse_faca!(tokens, env)
    bloco!(tokens, env, ["durante"])
    next!(tokens)
    par_expr!(tokens, env, "boleano")

end

max_stars_repo_name: GabrielTrettel/Portran

max_issues_repo_name: GabrielTrettel/Portran

max_forks_repo_name: GabrielTrettel/Portran


text:
"""
GenX: An Configurable Capacity Expansion Model
Copyright (C) 2021,  Massachusetts Institute of Technology
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.
A complete copy of the GNU General Public License v2 (GPLv2) is available
in LICENSE.txt.  Users uncompressing this from an archive may not have
received this license file.  If not, see <http://www.gnu.org/licenses/>.
"""

@doc raw"""
	configure_gurobi(solver_settings_path::String)

Reads user-specified solver settings from gurobi\_settings.yml in the directory specified by the string solver\_settings\_path.

Returns a MathOptInterface OptimizerWithAttributes Gurobi optimizer instance to be used in the GenX.generate_model() method.

The Gurobi optimizer instance is configured with the following default parameters if a user-specified parameter for each respective field is not provided:

 - FeasibilityTol = 1e-6 (Constraint (primal) feasibility tolerances. See https://www.gurobi.com/documentation/8.1/refman/feasibilitytol.html)
 - OptimalityTol = 1e-6 (Dual feasibility tolerances. See https://www.gurobi.com/documentation/8.1/refman/optimalitytol.html#parameter:OptimalityTol)
 - Presolve = -1 (Controls presolve level. See https://www.gurobi.com/documentation/8.1/refman/presolve.html)
 - AggFill = -1 (Allowed fill during presolve aggregation. See https://www.gurobi.com/documentation/8.1/refman/aggfill.html#parameter:AggFill)
 - PreDual = -1 (Presolve dualization. See https://www.gurobi.com/documentation/8.1/refman/predual.html#parameter:PreDual)
 - TimeLimit = Inf	(Limits total time solver. See https://www.gurobi.com/documentation/8.1/refman/timelimit.html)
 - MIPGap = 1e-4 (Relative (p.u. of optimal) mixed integer optimality tolerance for MIP problems (ignored otherwise). See https://www.gurobi.com/documentation/8.1/refman/mipgap2.html)
 - Crossover = -1 (Barrier crossver strategy. See https://www.gurobi.com/documentation/8.1/refman/crossover.html#parameter:Crossover)
 - Method = -1	(Algorithm used to solve continuous models (including MIP root relaxation). See https://www.gurobi.com/documentation/8.1/refman/method.html)
 - BarConvTol = 1e-8 (Barrier convergence tolerance (determines when barrier terminates). See https://www.gurobi.com/documentation/8.1/refman/barconvtol.html)
 - NumericFocus = 0 (Numerical precision emphasis. See https://www.gurobi.com/documentation/8.1/refman/numericfocus.html)

"""
function configure_gurobi(solver_settings_path::String)

    solver_settings = YAML.load(open(solver_settings_path))

    # Optional solver parameters ############################################
	# Constraint (primal) feasibility tolerances. See https://www.gurobi.com/documentation/8.1/refman/feasibilitytol.html
    FeasibilityTol = 1e-6
    if (haskey(solver_settings, "Feasib_Tol"))
        FeasibilityTol = solver_settings["Feasib_Tol"]
    end

	# Dual feasibility tolerances. See https://www.gurobi.com/documentation/8.1/refman/optimalitytol.html#parameter:OptimalityTol
    OptimalityTol = 1e-6
    if (haskey(solver_settings, "Optimal_Tol"))
        OptimalityTol = solver_settings["Optimal_Tol"]
    end

	# Controls presolve level. See https://www.gurobi.com/documentation/8.1/refman/presolve.html
	Presolve = -1
    if (haskey(solver_settings, "Pre_Solve"))
        Presolve = solver_settings["Pre_Solve"]
    end

	# Allowed fill during presolve aggregation. See https://www.gurobi.com/documentation/8.1/refman/aggfill.html#parameter:AggFill
    AggFill = -1
    if (haskey(solver_settings, "AggFill"))
        AggFill = solver_settings["AggFill"]
    end

	# Presolve dualization. See https://www.gurobi.com/documentation/8.1/refman/predual.html#parameter:PreDual
    PreDual = -1
    if (haskey(solver_settings, "PreDual"))
        PreDual = solver_settings["PreDual"]
    end

	# Limits total time solver. See https://www.gurobi.com/documentation/8.1/refman/timelimit.html
    TimeLimit = Inf
    if (haskey(solver_settings, "TimeLimit"))
        TimeLimit = solver_settings["TimeLimit"]
    end

	# Relative (p.u. of optimal) mixed integer optimality tolerance for MIP problems (ignored otherwise). See https://www.gurobi.com/documentation/8.1/refman/mipgap2.html
    MIPGap = 1e-4
    if (haskey(solver_settings, "MIPGap"))
        MIPGap = solver_settings["MIPGap"]
    end

	# Barrier crossver strategy. See https://www.gurobi.com/documentation/8.1/refman/crossover.html#parameter:Crossover
    Crossover = -1
    if (haskey(solver_settings, "Crossover"))
        Crossover = solver_settings["Crossover"]
    end

	# Algorithm used to solve continuous models (including MIP root relaxation). See https://www.gurobi.com/documentation/8.1/refman/method.html
    Method = -1
    if (haskey(solver_settings, "Method"))
        Method = solver_settings["Method"]
    end

	# Barrier convergence tolerance (determines when barrier terminates). See https://www.gurobi.com/documentation/8.1/refman/barconvtol.html
    BarConvTol = 1e-8
    if (haskey(solver_settings, "BarConvTol"))
        BarConvTol = solver_settings["BarConvTol"]
    end

	# Numerical precision emphasis. See https://www.gurobi.com/documentation/8.1/refman/numericfocus.html
    NumericFocus = 0
    if (haskey(solver_settings, "NumericFocus"))
        MyNumericFocus = solver_settings["NumericFocus"]
    end
    ########################################################################

    OPTIMIZER = optimizer_with_attributes(
        Gurobi.Optimizer,
        "OptimalityTol" => OptimalityTol,
        "FeasibilityTol" => FeasibilityTol,
        "Presolve" => Presolve,
        "AggFill" => AggFill,
        "PreDual" => PreDual,
        "TimeLimit" => TimeLimit,
        "MIPGap" => MIPGap,
        "Method" => Method,
        "BarConvTol" => BarConvTol,
        "NumericFocus" => NumericFocus,
        "Crossover" => Crossover,
    )

    return OPTIMIZER
end

max_stars_repo_name: Betristor/LTESOM

max_issues_repo_name: Betristor/LTESOM

max_forks_repo_name: Betristor/LTESOM