text:
# Author: Dharmesh Tarapore, dharmesh@bu.edu
# Date: 06/05/2014

# + References
# Kochenderfer, M., Espindle, L., Kuchar, J., and Griffith, J. D., "Correlated encounter model for cooperative aircraft in the national airspace system version 1.0," Project Report ATC-344, Lincoln Laboratory, 2008. Appendix D.
# "Introduction to TCAS II version 7.1," Tech. rep., Federal Aviation Administration, 2011.
# Kochenderfer, M. J., Chryssanthacopoulos, J. P., Kaelbling, L. P., and Lozano-Perez, T., "Model-based optimization of airborne collision avoidance logic," Project Report ATC-360, Lincoln Laboratory, 2010. Appendix I.

module GDQNACASImpl

export
    AddObserver,

    initialize,
    update,

    testThreat,
    selectRA,

    GDQNACAS,
    GDQNACASInput,
    GDQNACASResolutionAdvisory

using AbstractCollisionAvoidanceSystemImpl
using AbstractCollisionAvoidanceSystemInterfaces
using CommonInterfaces

using Util
using RLESUtils, Observers

import CommonInterfaces.addObserver
import CommonInterfaces.initialize
import CommonInterfaces.update
import AbstractCollisionAvoidanceSystemInterfaces.testThreat
import AbstractCollisionAvoidanceSystemInterfaces.selectRA

type GDQNACASInput

    t::Float64

    r::Float64
    r_d::Float64

    a::Float64
    a_d::Float64

    h::Vector{Float64}
    h_d::Vector{Float64}
end

type GDQNACASResolutionAdvisory

    h_d::Float64
end

type GDQNACAS <: AbstractCollisionAvoidanceSystem

    b_TCAS_activated::Bool
    RA::Union{SimpleTCASResolutionAdvisory,Void}

    observer::Observer

    function GDQNACAS()

        obj = new()

        obj.b_TCAS_activated = false
        obj.RA = nothing

        obj.observer = Observer()

        return obj
    end
end

addObserver(cas::GDQNACAS, f::Function) = add_observer(cas.observer, f)
addObserver(cas::GDQNACAS, tag::AbstractString, f::Function) = add_observer(cas.observer, tag, f)

function testThreat(cas::GDQNACAS, input::GDQNACASInput)

    b_ACAS_activated = false

    r = input.r
    r_dot = input.r_d

    a = input.a
    a_dot = input.a_d

    sl, tau, dmod, zthr, alim = simple_TCAS_thresholds(input.h[1])

    if (r_dot < 0 && (-(r - dmod) / r_dot <= tau || r < dmod)) && ((a_dot < 0 && -a / a_dot <= tau) || a <= zthr)
        b_ACAS_activated = true
    end

    return b_ACAS_activated
end

function selectRA(cas::GDQNACAS, input::GDQNACASInput)

    r = input.r
    r_dot = input.r_d

    a = input.a
    a_dot = input.a_d

    h1 = input.h[1]
    h2 = input.h[2]

    h1_dot = input.h_d[1]
    h2_dot = input.h_d[2]

    sl, tau, dmod, zthr, alim = simple_GDQNA_thresholds(input.h[1])

    ascend_cross = false
    ascend_dist = 0
    ascend_alim = false

    descend_cross = false
    descend_dist = 0
    descend_alim = false

    t_ = -r / r_dot

    # debug
    if false && t_ < 0
        println("t, r, r_dot, a, a_dot, h1, h2, h1_dot, h2_dot")
        println([input.t, input.r, input.r_d, input.a, input.a_d, input.h[1], input.h[2], input.h_d[1], input.h_d[2]]')

        println("sl, tau, dmod, zthr, alim")
        println([sl, tau, dmod, zthr, alim]')

        println("tests")
        println([r_dot < 0, -(r - dmod) / r_dot <= tau, r < dmod, a_dot < 0, -a / a_dot <= tau, a <= zthr]')

        println("selects")
        println(t_)
        println()

        @notify_observer(cas.observer, "debug", [false])

        return 0.
    end
    @assert t_ > 0

    h_dot_ascend = 1500 / 60

    h1_cpa = h1 + h_dot_ascend * t_
    h2_cpa = h2 + h2_dot * t_

    if (h1 <= h2 && h1_cpa >= h2_cpa) || (h1 >= h2 && h1_cpa <= h2_cpa)
        ascend_cross = true
    end

    ascend_dist = abs(h1_cpa - h2_cpa)
    if ascend_dist >= alim
        ascend_alim = true
    end

    h1_dot_descend = - 1500 / 60

    h1_cpa = h1 + h1_dot_descend * t_
    h2_cpa = h2 + h2_dot * t_

    if (h1 <= h2 && h1_cpa >= h2_cpa) || (h1 >= h2 && h1_cpa <= h2_cpa)
        descend_cross = true
    end

    descend_dist = abs(h1_cpa - h2_cpa)
    if descend_dist >= alim
        descend_alim = true
    end

    if ascend_cross
        if descend_alim
            resolution_advisory = - 1500 / 60
        elseif ascend_alim
            resolution_advisory = 1500 / 60
        else
            resolution_advisory = - 1500 / 60
        end
    elseif descend_cross
        if ascend_alim
            resolution_advisory = 1500 / 60
        elseif descend_alim
            resolution_advisory = - 1500 / 60
        else
            resolution_advisory = 1500 / 60
        end
    else
        if descend_alim && ascend_alim
            if descend_dist < ascend_dist
                resolution_advisory = - 1500 / 60
            else
                resolution_advisory = 1500 / 60
            end
        elseif descend_alim
            resolution_advisory = - 1500 / 60
        elseif ascend_alim
            resolution_advisory = 1500 / 60
        else
            if descend_dist > ascend_dist
                resolution_advisory = - 1500 / 60
            else
                resolution_advisory = 1500 / 60
            end
        end
    end

    # debug
    if false
        println("t, r, r_dot, a, a_dot, h1, h2, h1_dot, h2_dot")
        println([input.t, input.r, input.r_d, input.a, input.a_d, input.h[1], input.h[2], input.h_d[1], input.h_d[2]]')

        println("sl, tau, dmod, zthr, alim")
        println([sl, tau, dmod, zthr, alim]')

        println("tests")
        println([r_dot < 0, -(r - dmod) / r_dot <= tau, r < dmod, a_dot < 0, -a / a_dot <= tau, a <= zthr]')

        println("selects")
        println(Any[t_, ascend_cross, ascend_dist, ascend_alim, descend_cross, descend_dist, descend_alim, resolution_advisory]')
    end

    @notify_observer(cas.observer, "debug", Any[Any[input.t, input.r, input.r_d, input.a, input.a_d, input.h, input.h_d], Any[sl, tau, dmod, zthr, alim], Any[r_dot < 0, -(r - dmod) / r_dot <= tau, r < dmod, a_dot < 0, -a / a_dot <= tau, a <= zthr], Any[t_, ascend_cross, ascend_dist, ascend_alim, descend_cross, descend_dist, descend_alim, resolution_advisory]])

    return resolution_advisory
end

update(cas::GDQNACAS, input) = update(cas,convert(GDQNACASInput, input))

function update(cas::GDQNACAS, input::GDQNACASInput)

    if cas.b_ACAS_activated == false
        cas.b_ACAS_activated = testThreat(cas, input)

        if cas.b_ACAS_activated
            cas.RA = GDQNACASResolutionAdvisory(selectRA(cas, input))
        end
    end

    if cas.RA == nothing
        return nothing
    else
        return cas.RA
    end
end

function initialize(cas::SimpleTCAS)
    cas.b_ACAS_activated = false
    cas.RA = nothing
end

function simple_GDQNA_thresholds(h)

    if h < 1000
        sl = 2
        tau = 0
        dmod = 0
        zthr = 0
        alim = 0
    elseif h < 2350
        sl = 3
        tau = 15
        dmod = 0.2 * 6076.12
        zthr = 600
        alim = 300
    elseif h < 5000
        sl = 4
        tau = 20
        dmod = 0.35 * 6076.12
        zthr = 600
        alim = 300
    elseif h < 10000
        sl = 5
        tau = 25
        dmod = 0.55 * 6076.12
        zthr = 600
        alim = 350
    elseif h < 20000
        sl = 6
        tau = 30
        dmod = 0.80 * 6076.12
        zthr = 600
        alim = 400
    elseif h < 42000
        sl = 7
        tau = 35
        dmod = 1.10 * 6076.12
        zthr = 700
        alim = 600
    else
        sl = 7
        tau = 35
        dmod = 1.10 * 6076.12
        zthr = 800
        alim = 700
    end

    return sl, tau, dmod, zthr, alim
end

end


text:
import GeometryBasics: normals, faces, decompose, normals
import GLAbstraction: INVALID_ATTRIBUTE, attribute_location, GEOMETRY_DIVISOR

function BasicMesh(geometry::T, ft = TriangleFace{3,GLint}) where {T}
    return error("Please implement a `BasicMesh` constructor for type $T.")
end

function BasicMesh(geometry::AbstractGeometry{D,T}, ft = TriangleFace{GLint}) where {D,T}
    vertices = collect(decompose(Point{D,T}, geometry))
    faces    = collect(decompose(ft, geometry))
    norms    = collect(normals(vertices, faces))
    return BasicMesh(vertices, faces, norms)
end

function BasicMesh(geometry::HyperSphere, complexity = 2)
    vertices, normals, faces = generate_sphere(complexity)
    return BasicMesh(vertices, faces, normals)
end

function BasicMesh(geometry::String)
    faces, vertices, normals = getfield.((load(geometry),), [:faces, :vertices, :normals])
    return BasicMesh(vertices, faces, Vec3f0.(normals))
end

function BasicMesh(vec_geometry::Vector)
    vertices = Point3f0.(vec_geometry)
    faces    = SimplexFace{1}.([i for i in 1:length(vec_geometry)])
    normals  = Vec3f0[]
    return BasicMesh(vertices, faces, normals)
end

Base.eltype(::Type{BasicMesh{D,T,FT}}) where {D,T,FT} = (D, T, FT)
Base.eltype(mesh::BM) where {BM<:BasicMesh} = eltype(BM)

basicmesh(mesh::BasicMesh)          = mesh
vertices(mesh::AbstractGlimpseMesh) = basicmesh(mesh).vertices
normals(mesh::AbstractGlimpseMesh)  = basicmesh(mesh).normals
faces(mesh::AbstractGlimpseMesh)    = basicmesh(mesh).faces

facelength(mesh::AbstractGlimpseMesh) = facelength(basicmesh(mesh))
facelength(mesh::BasicMesh{D,T,FT} where {D,T,FD}) where {FT} = length(FT)

Base.length(mesh::AbstractGlimpseMesh) = length(vertices(mesh))

function Base.isequal(mesh::BasicMesh, mesh2::BasicMesh)
    return mesh.faces == mesh2.faces && mesh.vertices == mesh2.vertices
end
import Base: ==
==(mesh::BasicMesh, mesh2::BasicMesh) = isequal(mesh, mesh2)

AttributeMesh(attributes, args...) = AttributeMesh(attributes, BasicMesh(args...))
AttributeMesh(args...; attributes...) = AttributeMesh(attributes.data, BasicMesh(args...))

Base.eltype(::Type{AttributeMesh{AT,BM}}) where {AT,BM} = (AT, eltype(BM)...)
Base.eltype(mesh::AM) where {AM<:AttributeMesh} = eltype(AM)

basicmesh(mesh::AttributeMesh) = mesh.basic

function generate_buffers(program::Program, mesh::BasicMesh)
    buffers = BufferAttachmentInfo[]
    for n in (:vertices, :normals)
        loc = attribute_location(program, n)
        if loc != INVALID_ATTRIBUTE
            push!(buffers,
                  BufferAttachmentInfo(n, loc, Buffer(getfield(mesh, n)), GEOMETRY_DIVISOR))
        end
    end
    return buffers
end

function generate_buffers(program::Program, mesh::AttributeMesh{AT}) where {AT}
    buffers = generate_buffers(basicmesh(mesh), program)
    buflen  = length(mesh)
    for (name, val) in pairs(mesh.attributes)
        loc = attribute_location(program, name)
        if loc != INVALID_ATTRIBUTE
            vallen = length(val)
            if vallen == buflen
                push!(buffers,
                      BufferAttachmentInfo(name, loc, Buffer(val), GEOMETRY_DIVISOR))
            elseif !isa(val, Vector)
                push!(buffers,
                      BufferAttachmentInfo(name, loc, Buffer(fill(val, buflen)),
                                           GEOMETRY_DIVISOR))
            end
        end
    end
    return buffers
end

function GLA.VertexArray(program::Program, mesh::AbstractGlimpseMesh; extra_attributes...)
    return VertexArray(generate_buffers(program, mesh; extra_attributes...),
                       faces(mesh) .- GLint(1))
end

ext: jl


text:
# pre script for movies
project(C=(-73.8333,40.75), E=(-80.133,25.75), G=30, Q=true, write="flight_path.txt")
grdmath("-R-100/-70/10/50 -I0.5 X Y MUL = USEast_Coast.nc")	# Just a fake one since original was deleted from GMT server
grdgradient("USEast_Coast.nc", A=90, N=:t1, G="int_US.nc")
makecpt(C=:globe, H=true, cptname="globe_US.cpt")


text:
module TestSubgraphTrackingPath
import Unregistered

greet() = print("Hello World!")
addfive(x) = Unregistered.plusfive(x)

end # module


text:
Base.isequal(F::C, G::C) where {C <: ComponentData} =
    all(f -> isequal(getfield(F, f), getfield(G, f)), 1:nfields(F))::Bool

Base.:(==)(F::C, G::C) where {C <: ComponentData} =
    all(f -> getfield(F, f)== getfield(G, f), 1:nfields(F))::Bool

@inline function Base.hash(c::C, h::UInt) where {C <: ComponentData}
    for f in nfields(c)
        h = hash(getfield(c, f), h)
    end
    return h
end

"Can be used to specify the type of component storage to be used for a given `ComponentData`."
component_type(::Type{<:ComponentData}) = Component

@inline indices_iterator(a::AbstractComponent) = a.indices

"""
The most basic Component type.

Indexing into a component with an `Entity` will return the data linked to that entity,
indexing with a regular `Int` will return directly the `ComponentData` that is stored in the data
vector at that index, i.e. generally not the storage linked to the `Entity` with that `Int` as id.
"""
struct Component{T <: ComponentData} <: AbstractComponent{T}
    indices::Indices
    data::Vector{T}
end

Component{T}() where {T} = Component(Indices(), T[])

"""
A shared component works very much like a normal component except that it tries to not have duplicate
data for different entities. This should be used for very large `ComponentData`.
"""
struct SharedComponent{T <: ComponentData} <: AbstractComponent{T}
    indices::Indices
    data::Vector{Int} # saves the indices into the shared for each of the entities
    shared::Vector{T}
end

SharedComponent{T}() where {T <: ComponentData} = SharedComponent{T}(Indices(), Int[], T[])

##### BASE Extensions ####
Base.eltype(::Type{<:AbstractComponent{T}}) where T = T

Base.length(c::AbstractComponent) = length(c.data)

Base.in(i::Integer, c::AbstractComponent) = in(i, c.indices)
Base.in(e::Entity, c::AbstractComponent)  = in(e.id, c)

Base.isempty(c::AbstractComponent) = isempty(c.data)

function Base.delete!(c::AbstractComponent, es::Vector{Entity})
    for e in es
        if e in c
            pop!(c, e)
        end
    end
end

function Base.permute!(c::AbstractComponent, permvec)
    permute!(c.data, permvec)
    permute!(c.indices, permvec)
end

Base.@propagate_inbounds @inline Base.getindex(c::Component, e::Entity) = c.data[c.indices[e.id]]
Base.@propagate_inbounds @inline Base.getindex(c::SharedComponent, e::Entity) = c.shared[c.data[c.indices[e.id]]]
Base.@propagate_inbounds @inline Base.getindex(c::Component, i::Integer) = c.data[i]
Base.@propagate_inbounds @inline Base.getindex(c::SharedComponent, i::Integer) = c.shared[c.data[i]]

@inline function Base.setindex!(c::Component{T}, v::T, e::Entity) where {T}
    eid = e.id
    @boundscheck if !in(e, c)
        push!(c.indices, eid)
        push!(c.data, v)
        return v
    end
    @inbounds c.data[c.indices[eid]] = v
    return v
end
@inline function Base.setindex!(c::SharedComponent{T}, v::T, e::Entity) where {T}
    eid = e.id
    t_shared_id = findfirst(x->x == v, c.shared)
    shared_id = t_shared_id === nothing ? (push!(c.shared, v); length(c.shared)) : t_shared_id
    @boundscheck if !in(e, c)
        push!(c.indices, eid)
        push!(c.data, shared_id)
        return v
    end
    @inbounds c.data[c.indices[eid]] = shared_id
    return v
end

function Base.empty!(c::Component)
    empty!(c.indices)
    empty!(c.data)
    return c
end
function Base.empty!(c::SharedComponent)
    empty!(c.indices)
    empty!(c.data)
    empty!(c.shared)
    return c
end

function swap_order!(c::AbstractComponent, e1::Entity, e2::Entity)
    @boundscheck if !in(e1, c)
        throw(BoundsError(c, e1))
    elseif !in(e2, c)
        throw(BoundsError(c, e2))
    end
    @inbounds begin
        id1, id2 = swap_order!(c.indices, e1.id, e2.id)
        c.data[id1], c.data[id2] = c.data[id2], c.data[id1]
    end
end

function pop_indices_data!(c::AbstractComponent, e::Entity)
    @boundscheck if !in(e, c)
        throw(BoundsError(c, e))
    end
    n = length(c)
    @inbounds begin
        id = c.indices[e.id]
        v = c.data[id]
        c.data[id] = c.data[end]
        pop!(c.data)
        pop!(c.indices, e.id)
        return v
    end
end

Base.pop!(c::Component, e::Entity) = pop_indices_data!(c, e)

function Base.pop!(c::SharedComponent, e::Entity)
    i = pop_indices_data!(c, e)
    idvec = c.data
    val = c.shared[i]
    if !any(isequal(i), idvec)
        for j in 1:length(idvec)
            if idvec[j] > i
                idvec[j] -= 1
            end
        end
        deleteat!(c.shared, i)
    end
    return val
end

@inline Base.iterate(c::Component, args...) = iterate(c.data, args...)
@inline Base.iterate(c::SharedComponent, args...) = iterate(c.shared, args...)

function ensure_entity_id!(c::AbstractComponent, e::Int, id::Int)
    indices = c.indices
    @inbounds packed_id = indices[e]
    if packed_id != id
        @inbounds id_to_swap = indices.packed[id]
        swap_order!(indices, e, id_to_swap)
        c.data[id], c.data[packed_id] = c.data[packed_id], c.data[id]
    end
    return true
end

function shared_entity_ids(cs)
    l, id = findmin(map(length, cs))
    shortest = cs[id]
    shared_entity_ids = Int[]
    for (i, e) in enumerate(shortest.indices)
        if all(x->in(e, x.indices), cs)
            push!(shared_entity_ids, e)
        end
    end
    return shared_entity_ids
end

Base.sortperm(c::SharedComponent) = sortperm(c.data)

@inline function Base.hash(c::C, h::UInt) where {C <: AbstractComponent}
    for f in nfields(c)
        h = hash(getfield(c,f), h)
    end
    return h
end
########################################
#                                      #
#            Iteration                 #
#                                      #
########################################
struct EntityIterator{T <: Union{IndicesIterator,Indices,AbstractGroup}}
    it::T
end

Base.eltype(::EntityIterator) = Entity
Base.IteratorSize(i::EntityIterator) = Base.IteratorSize(i.it)
Base.length(i::EntityIterator) = length(i.it)

function Base.iterate(i::EntityIterator, state = 1)
    n = iterate(i.it, state)
    n === nothing && return n
    return Entity(n[1]), n[2]
end

macro entities_in(indices_expr)
    expr, t_sets, t_orsets = expand_indices_bool(indices_expr)
    if length(t_sets) == 1 && isempty(t_orsets) && expr.args[2] isa Symbol
        return esc(:(Overseer.EntityIterator(Overseer.indices_iterator($(t_sets[1])))))
    else
        return esc(quote
            t_comps = $(Expr(:tuple, t_sets...))
            t_or_comps = $(Expr(:tuple, t_orsets...))
            sets = map(Overseer.indices_iterator, t_comps)
            orsets = map(Overseer.indices_iterator, t_or_comps)
            if isempty(sets)
                minlen, minid = findmin(map(length, orsets))
                t_shortest = orsets[minid]
            else
                minlen, minid = findmin(map(length, sets))
                t_shortest = sets[minid]
            end
            if $(!isempty(t_orsets))
                shortest = deepcopy(t_shortest)
                for s in orsets
                    union!(shortest, s)
                end
            else
                shortest = t_shortest
            end
            Overseer.EntityIterator(Overseer.IndicesIterator(shortest, x->$expr))
        end)
    end
end

Base.getindex(iterator::EntityIterator, i) = Entity(iterator.it.shortest.packed[i])

function Base.:(==)(c1::C1, c2::C2) where {C1 <: AbstractComponent, C2 <: AbstractComponent}
    if eltype(C1) != eltype(C2) ||length(c1) != length(c2)
        return false
    elseif length(c1) > 20 && hash(c1) != hash(c2)
        return false
    else
        return all(e -> (e in c2) && (@inbounds c2[e] == c1[e]), @entities_in(c1))
    end
end

##############################
#                            #
#     Component Macros       #
#                            #
##############################

function process_typedef(typedef, mod)
    global td = nothing
    MacroTools.postwalk(typedef) do x
        if @capture(x, struct T_ fields__ end | mutable struct T_ fields__ end)
            global td = T
        end
        x
    end
    tn = MacroTools.namify(td)
    if @capture(td, T_ <: V_)
        if !Base.eval(mod, :($V <: Overseer.ComponentData))
            error("Components can only have supertypes which are subtypes of ComponentData.")
        else
            return typedef, tn
        end
    else
        typedef_ = MacroTools.postwalk(typedef) do x
            if MacroTools.isexpr(x) && x.head == :struct
                x.args[2] = :($(x.args[2]) <: Overseer.ComponentData)
            end
            x
        end
        return typedef_, tn
    end
end

macro component(typedef)
	return esc(Overseer._component(typedef, __module__))
end
function _component(typedef, mod)
    t = process_typedef(typedef, mod)
	t1, tn = t
	return quote
	    $t1
        Overseer.component_type(::Type{$tn}) = Overseer.Component
    end
end

macro shared_component(typedef)
    return esc(Overseer._shared_component(typedef, __module__))
end

function _shared_component(typedef, mod)
    t = process_typedef(typedef, mod)
    t1, tn = t
    return quote
        $t1
       	Overseer.component_type(::Type{$tn}) = Overseer.SharedComponent
    end
end


text:
include("libavresample_h.jl")

#include("avresample.jl")


text:
# MIT License
# Copyright (c) 2017: Xavier Gandibleux, Anthony Przybylski, Gauthier Soleilhac, and contributors.

# ==========================================================================
# vOpt solver
#   Part of the open source prototype issued from the ANR-DFG research project
# Coordinator:
#   Xavier.Gandibleux@univ-nantes.fr
# --------------------------------------------------------------------------
# Content of this package:
#   Exact algorithm for solving the 1/./(sumCi , Tmax) scheduling problem
# Contributor(s):
#   Pauline Chatellier-Bertin
#   Xavier Gandibleux
# Version and Release date:
#   V0.1 - April 28, 2017
# ==========================================================================

# ==========================================================================
# Types and structures
# ==========================================================================
# Environment variables
struct t_environment
	# for display's options: false => mute, true => verbose
	displayYN      :: Bool # display the generation of all efficient solutions and non-dominated points
	displayPrint   :: Bool # display all the prints to follow the algorithm's activity
	displayGraphic :: Bool # display the results on a graphic
end

# ==========================================================================
# Type of a instance for the scheduling problem presented in the paper Morita et al., 2001 (FCDS)
struct _2OSP
	n ::Int      # number of tasks (positive integer value)
	p ::Vector{Int}# vector of processing time (positive integer values)
	d ::Vector{Int}# vector of due dates (non-negative integer values)
	r ::Vector{Int}#vector of release dates (non-negative integer values)
	w ::Vector{Int}# vector of weights (non-negative integer values)
end

Base.show(io::IO, id::_2OSP) = begin
		print(io, "Bi-Objective Scheduling Problem with $(id.n) tasks.")
		print(io, "\nProcessing times : ") ; show(IOContext(io, :limit=>true), id.p)
		print(io, "\nDue dates : ") ; show(IOContext(io, :limit=>true), id.d)
		if any(x->x!=0, id.r)
				print(io, "\nRelease dates : ") ; show(IOContext(io, :limit=>true), id.r)
		end
		if any(x->x!=1, id.w)
				print(io, "\nWeights : ") ; show(IOContext(io, :limit=>true), id.w)
		end
end

# ==========================================================================
# Type of a solution for the scheduling problem presented in the paper Morita et al., 2001 (FCDS)
mutable struct t_solution
	x ::Vector{Int}# vector of index of jobs in the solution
	z1::Int   # performance objective 1 (integer)
	z2::Int   # performance objective 2 (integer)
end

# ==========================================================================
# Instance's Generators
# ==========================================================================
# Generate a didactic instance
function generateDidacticInstance(idInstance::String)::_2OSP
	if     idInstance == "2001"
		# From the paper:
		#   Hiroyuki Morita, Xavier Gandibleux, Naoki Katoh.
		#   Experimental feedback on biobjective permutation scheduling problems solved with a population heuristic.
		#   Foundations of Computing and Decision Sciences 26 (1), 23-50.
		#   http://fcds.cs.put.poznan.pl/FCDS2/PastIssues.aspx
		nTasks = 4
		data = _2OSP(nTasks, [3, 4, 5, 6], [20, 16, 11, 5], [1, 1, 1, 1], ones(nTasks))
		return data

	elseif idInstance == "1980_4"
		# From the paper:
		#   Luc Van Wassenhove and Ludo Gelders
		#   Solving a bicriterion scheduling problem.
		#   European Journal of Operational Research 4 (1980) 42-48.
		nTasks = 4
		data = _2OSP(nTasks, [2, 4, 3, 1], [1, 2, 4, 6], [1, 1, 1, 1], ones(nTasks))
		# data = _2OSP(nTasks, [2, 3, 1, 2], [3, 4, 5, 6], [1, 1, 1, 1], ones(nTasks))
		return data

	elseif idInstance == "1980_10"
		# From the paper:
		#   Luc Van Wassenhove and Ludo Gelders
		#   Solving a bicriterion scheduling problem.
		#   European Journal of Operational Research 4 (1980) 42-48.
		nTasks = 10
		data = _2OSP(nTasks,
					[9, 9, 6, 7, 2, 4, 7, 2, 7, 8],
					[32, 49, 7, 25, 55, 9, 54, 40, 52, 51],
					[1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
					ones(nTasks))
		return data

	end
end

# ==========================================================================
# Generate a parameterized random instance
function generateRandomInstance(nTasks::Int, pMax::Int, dMax::Int, wMax::Int)::_2OSP
	data = _2OSP(nTasks, rand(1:pMax, nTasks), rand(1:dMax, nTasks), rand(1:wMax, nTasks), ones(nTasks))
	return data
end

# ==========================================================================
# Generate a parameterized instance according to (Yagiura and Ibaraki, 1996)
function generateHardInstance(nTasks::Int;  pMax::Int = 30, LF::Float64 = 0.3, RDD::Float64 = 0.9)::_2OSP
	# The generator follows the rules provided in the paper:
	#   Mutsunori Yagiura, Toshihide Ibaraki.
	#   Genetic and local search algorithms as robust and simple optimization tools.
	#   In "Meta-Heuristics: Theory and Applications" (I. Osman and J. Kelly Edts). Kluwer, pp.63-82, 1996.

	# --------------------------------------------------------------------------
	# The parameters are:
	#   nTasks : number of tasks for the scheduling problem
	#     nTasks > 0
	#   pMax : upper value of p_i
	#     1 <= pMax <= 30
	#   LF : Average Lateness Factor (facteur de retard moyen)
	#     0.1 <= LF <= 0.5
	#   RDD : Relative Range of Duedate (interval relatif des dates echues)
	#     0.8 <= RDD <= 1.0

	data_p = rand(1:pMax, nTasks)
	MP = sum(data_p)
	data_d = max.(0 , rand( floor(Int, (1-LF-RDD/2)*MP) : floor(Int, (1-LF+RDD/2)*MP) , nTasks))
	data = _2OSP(nTasks, data_p, data_d, ones(Int,nTasks), ones(nTasks))
	return data
end

# ==========================================================================
# Optimization algorithmsmax.(0 , rand( floor(Int, (1-LF-RDD/2)*MP) : floor(Int, (1-LF+RDD/2)*MP) , nTasks))
# ==========================================================================
# minimize the flowtime on a single machine (Smith's rule)
function computeMinFlowtime(env::t_environment, data::_2OSP)::Tuple{Vector{Int}, Int}
	# minimise f1 : flowtime (SPT-rule)
	SPT = sortperm(data.p)
	somCi = 0
	somPi = 0
	c = zeros(Int,data.n)
	for i=1:data.n
		c[SPT[i]] = somPi + data.p[SPT[i]]
		somPi = somPi + data.p[SPT[i]]
		somCi = somCi + c[SPT[i]]
	end
	if env.displayPrint == true
		println("minimum f1 (min flowtime) = ", somCi)
	end
	return SPT, somCi
end

# ==========================================================================
# minimize the maximum tardiness on a single machine
function computeMinMaxTardiness(env::t_environment, data::_2OSP)::Tuple{Vector{Int}, Int}
	# minimise f2 : maximum tardiness (EDD-rule)
	EDD = sortperm(data.d)
	maxT = 0
	somPi = 0
	c = zeros(Int,data.n)
	for i=1:data.n
		c[EDD[i]] = somPi + data.p[EDD[i]]
		somPi = somPi + data.p[EDD[i]]
		maxT = max(maxT, c[EDD[i]]-data.d[EDD[i]])
	end
	if env.displayPrint == true
		println("minimum f2 (max tardiness) = ", maxT)
	end
	return EDD, maxT
end

# ==========================================================================
# minimize the flowtime on a single machine (modified Smith's backward scheduling rule)
function smith_modifie(env::t_environment, data::_2OSP, I::Matrix{Int}, R::Int, D::Vector{Int})::Tuple{Vector{Int}, Bool}
	sol = zeros(Int,data.n)
	k = data.n
	trouve = true

	# Ensemble des taches triees par ordre lexicographique de leur processing time puis de leur due date
	N = [I[i,3] for i = 1:data.n]

	# Assignation des taches a chaque position en partant de la fin (on decremente k)
	# jusqu'a les avoir toutes assignees ou lorsqu'il n'y a plus de tache i respectant D_i >= R
	while 0 < k && trouve

		i = length(N)
		trouve = false

		# Parcours des taches de l'ensemble N,
		# en partant de celle ayant le plus grand p_i, en cas de p_i egaux celle ayant le plus grand d_i
		while 0 < i && !trouve

			# Si la tache i respecte la conditon D_i >= R
			if D[N[i]] >= R
				sol[k] = N[i] # on l'assigne à la position k
				R = R - data.p[N[i]] # R = R - p_i
				deleteat!(N, i) # on supprime i de l'ensemble N
				k = k-1
				trouve = true
			else
				i = i-1
			end

		end
	end

	return sol, trouve

end

# ==========================================================================
# minimize both flowtime and maximum tardiness on a single machine
function computeExactFlowtimeMaxTardiness(env::t_environment, data::_2OSP)::Vector{t_solution}
	# The algorithm implemented is presented in the paper:
	#   Luc Van Wassenhove and Ludo Gelders
	#   Solving a bicriterion scheduling problem.
	#   European Journal of Operational Research 4 (1980) 42-48.

	# --------------------------------------------------------------------------
	# YN est un tableau contenant tous les points non-domines
	YN = t_solution[]

	# --------------------------------------------------------------------------
	# Trie des taches par ordre lexicographique
	# sur leur processing time puis leur due date
	I = [data.p data.d 1:data.n]

	I = @static if VERSION > v"0.7-"
			sortslices(I, dims=1)
		else
			sortrows(I)
		end

	# --------------------------------------------------------------------------
	# Initialisation de R avec la somme des processing time
	R = sum(data.p)

	# --------------------------------------------------------------------------
	# Initialisation de delta avec la somme des processing time, puis des D_i = d_i - delta
	delta = sum(data.p)
	D = [data.d[i] + delta for i = 1:data.n]

	# --------------------------------------------------------------------------
	# Recherche d'une 1ere solution X avec les R et D_i initiaux
	X, existeX = smith_modifie(env, data, I, R, D)

	# --------------------------------------------------------------------------
	# Recherche de l'ensemble des solutions efficaces
	while existeX

		sol = t_solution(X, 0, 0)
		evaluateSolution!(env, data, sol) # (re)evalue la solution sur les 2 objectifs
		push!(YN, sol) # ajoute le point non-domine a l'ensemble YN

		# Affichage de la solution trouvée
		if env.displayYN == true
			println("")
			println("     X  (scheduling) = ", sol.x)
			println("     z1 (total flow time)   = ", sol.z1)
			println("     z2 (maximum tardiness) = ", sol.z2)
			println("")
		end

		# plotEfficientGraphicY(env, sol)

		# Si z2 peut être amélioré on cherche de nouvelle solution sinon on arrête
		if sol.z2 != 0
			# Mise à jour de delta et D_i
			delta = sol.z2 - 1
			for j = 1:data.n
				D[j] = data.d[j] + delta
			end
			X, existeX = smith_modifie(env, data, I, R, D)
		else
			existeX = false
		end #if
	end #while

	return YN

end

# ==========================================================================
# Bi-objective evaluation of a solution
function evaluateSolution!(env::t_environment, data::_2OSP, sol::t_solution)
	# a solution here is a feasible scheduling of tasks
	c = 0; sol.z1 = 0; sol.z2 = 0
	for i=1:data.n
		# completion time de la tache i
		c = c + data.p[sol.x[i]]
		# calcule la somme des c_i (total flow time))
		sol.z1 = sol.z1 + c
		# calcule le retard maximum (maximum tardiness)
		sol.z2 = max(sol.z2, c - data.d[sol.x[i]] )
	end
end

# ==========================================================================
# Output on screen
# ==========================================================================
# display the values of the instance
function displayInstance(env::t_environment, data::_2OSP)
	if env.displayPrint == true
		println("Instance :")
		println(" n = ", data.n)
		println(" p = ", data.p)
		println(" d = ", data.d)
	end
end

# ==========================================================================
# display the points corresponding to optimal solutions for objectives separately
function displayOptimal(env::t_environment, optf1::t_solution, optf2::t_solution)
	if env.displayPrint == true
		println("")
		println("     X optimal f1           = ", optf1.x)
		println("     z1 (total flowtime)    = ", optf1.z1)
		println("     z2 (maximum tardiness) = ", optf1.z2)
		println("")
		println("     X optimal f2           = ", optf2.x)
		println("     z1 (total flowtime)    = ", optf2.z1)
		println("     z2 (maximum tardiness) = ", optf2.z2)
		println("")
		println("------------------------------------------------------------------")
	end
end

# ==========================================================================
# display on screen a summary of the solving process
function displaySummary(env::t_environment, YN, elapsedTime)
	if env.displayPrint == true
		println("")
		println("     Number of non-dominated points = ", length(YN))
		println("     Elapsed time (seconds)         = ", elapsedTime)
		println("")
	end
end

# ==========================================================================
# Output on graphics
# ==========================================================================
# initiate the legends of the graphic in the objective space
# function setupGraphicY(env::t_environment, titleFigure, axisX, axisY)
#   if env.displayGraphic == true
#     title(titleFigure)
#     xlabel(axisX)
#     ylabel(axisY)
#   end
# end

# ==========================================================================
# plot the optimal points corresponding to optimal solutions for both objectives separately
# function plotOptimalGraphicY(env::t_environment, optf1::t_solution, optf2::t_solution)
#   if env.displayGraphic == true
#     plot(optf1.z1,optf1.z2, color="green",linestyle="",marker="D", label="opt")
#     plot(optf2.z1,optf2.z2, color="green",linestyle="",marker="D", label="opt")
#   end
# end

# ==========================================================================
# plot one non-dominated point
# function plotEfficientGraphicY(env::t_environment, sol::t_solution)
#   if env.displayGraphic == true
#     plot(sol.z1,sol.z2, color="cyan",linestyle="",marker="o", label="YN")
#   end
# end

function solveOSP(data::_2OSP, displayYN, displayPrint)
	# --------------------------------------------------------------------------
	env = t_environment(displayYN, displayPrint, false)

	# display the values of the instance
	displayInstance(env, data)

	# --------------------------------------------------------------------------
	# Elements pour la representation graphique de l'espace des objectifs
	# setupGraphicY(env, "Y (objective space)", "z1 (total flow time)", "z2 (Maximum tardiness)")

	# --------------------------------------------------------------------------
	# Initialise le timer
	tstart = time_ns()

	# --------------------------------------------------------------------------
	# Calcul des solutions optimales pour les 2 objectifs pris separement
	optf1 = t_solution(zeros(data.n), 0, 0)
	optf1.x, optf1.z1 = computeMinFlowtime(env, data)
	evaluateSolution!(env, data, optf1) # (re)evalue la solution sur les 2 objectifs

	optf2 = t_solution(zeros(data.n), 0, 0)
	optf2.x, optf2.z2 = computeMinMaxTardiness(env, data)
	evaluateSolution!(env, data, optf2) # (re)evalue la solution sur les 2 objectifs

	# --------------------------------------------------------------------------
	# plot on graphic the optimal points corresponding to optimal solutions for both objectives separately
	# plotOptimalGraphicY(env, optf1, optf2)

	# --------------------------------------------------------------------------
	# display on screen the optimal solutions for both objectives separately
	displayOptimal(env, optf1, optf2)

	# --------------------------------------------------------------------------
	# Calcul des points non-domines pour les 2 objectifs pris simultanement
	YN = computeExactFlowtimeMaxTardiness(env, data)

	# Releve le timer et donne le temps utilise par la resolution
	elapsedTime = (time_ns() - tstart) * 1e-9

	# --------------------------------------------------------------------------
	# display on screen a summary of the solving process
	displaySummary(env, YN, elapsedTime)

	return map(x -> x.z1, YN), map(x -> x.z2, YN), map(x -> x.x, YN)

	# ==========================================================================

end

function set2OSP(n::Int, p::Vector{Int}, d::Vector{Int}, r::Vector{Int}=zeros(Int,n), w::Vector{Int}=ones(Int,n))
	@assert n==length(p)==length(d)==length(w)
	@assert all(x->x>0, p)
	@assert all(x->x>=0, d)
	@assert all(x->x>=0, r)
	@assert all(x->x>=0, w)
	_2OSP(n,p,d,r,w)
end
set2OSP(p::Vector{Int},d::Vector{Int},r::Vector{Int}=zeros(Int,length(p)),w::Vector{Int}=ones(Int, length(p))) = set2OSP(length(p),p,d,r,w)

struct OSPSolver
	solve::Function
end

function OSP_VanWassenhove1980(;displayYN=false, displayPrint=false)::OSPSolver
	return OSPSolver((id::_2OSP) -> solveOSP(id,displayYN,displayPrint))
end

function vSolve(id::_2OSP, solver::OSPSolver = OSP_VanWassenhove1980())
	solver.solve(id)
end

function load2OSP(fname::AbstractString)
	f = open(fname)
	n = parse(Int, readline(f))
	data = convert(Matrix{Int}, readdlm(f))
	p = data[1,:]
	d = data[2,:]
	r = data[3,:]
	w = data[4,:]
	close(f)
	return set2OSP(p,d,r,w)
end

max_stars_repo_name: vOptSolver/vOptSpecific

max_issues_repo_name: vOptSolver/vOptSpecific

max_forks_repo_name: vOptSolver/vOptSpecific


text:
#!/usr/bin/env julia

using ArgParse
using Printf

# smallest cube:
#
# local_1d_3d_map = Dict(1 => (-1, -1,  1),
#                        2 => ( 1, -1,  1),
#                        3 => ( 1, -1, -1),
#                        4 => (-1, -1, -1),
#                        5 => (-1,  1, -1),
#                        6 => ( 1,  1, -1),
#                        7 => ( 1,  1,  1),
#                        8 => (-1,  1,  1))

basic_curve = [-1 +1 +1 -1 -1 +1 +1 -1;
               -1 -1 -1 -1 +1 +1 +1 +1;
               +1 +1 -1 -1 -1 -1 +1 +1]

rot_eye = [1 0 0; 0 1 0; 0 0 1]
rot_x_c = [1 0 0; 0 0 1; 0 -1 0]
rot_x_a = [1 0 0; 0 0 -1; 0 1 0]
rot_y_c = [0 0 -1; 0 1 0; 1 0 0]
rot_y_a = [0 0 1; 0 1 0; -1 0 0]
rot_z_c = [0 1 0; -1 0 0; 0 0 1]
rot_z_a = [0 -1 0; 1 0 0; 0 0 1]

function hilbert3d(n_order::Int)
    # =========
    # variables
    # =========
    n_nodes = 8^n_order
    node_chain = zeros(Int, (3, n_nodes))

    if n_order == 1
        node_chain = basic_curve
    else
        size_node  = 8^(n_order - 1)
        for node in 1:8
            coor_shift = basic_curve[:, node] .* 2^(n_order-1)
            node_coors = hilbert3d(n_order - 1)

            if node == 1
                rot_mat = rot_z_c * rot_y_a
            elseif node == 2
                rot_mat = rot_z_a * rot_x_c
            elseif node == 3
                rot_mat = rot_eye
            elseif node == 4
                rot_mat = rot_z_c * rot_x_c
            elseif node == 5
                rot_mat = rot_z_a * rot_x_a
            elseif node == 6
                rot_mat = rot_eye
            elseif node == 7
                rot_mat = rot_z_c * rot_x_a
            elseif node == 8
                rot_mat = rot_z_a * rot_y_a
            end
            node_chain[:, (node - 1) * size_node + 1 : node * size_node] = rot_mat * node_coors .+ coor_shift
        end
    end
    return node_chain
end

function parse_commandline()
    s = ArgParseSettings()

    @add_arg_table s begin
        "n_order"
        help     = "Order of the curve."
        required = true
        arg_type = Int
    end

    return parse_args(s)
end

if abspath(PROGRAM_FILE) == @__FILE__
    args = parse_commandline()
    curve = hilbert3d(args["n_order"])

    of_name = @sprintf("HILBERT_3D_CURVE_ORDER_%02d.dat", args["n_order"])
    of = open(of_name, "w")
    for i in 1:size(curve)[2]
        @printf(of, " %5d   %8d %8d %8d \n", i, curve[1, i], curve[2, i], curve[3, i])
    end
    close(of)
end


text:
module TestOldTutorialMissings
include("preamble.jl")

argext_step(should_update) =
    (old, (index, value)) ->
        if old === nothing || should_update(old[2], value)
            (index, value)
        else
            old
        end

xf_scanext(should_update) = Scan(argext_step(should_update), nothing)

slow_xf_fullextrema =
    opcompose(Zip(Count(), NotA(Missing)), Zip(xf_scanext(>), xf_scanext(<)))

slow_xf_argextrema = opcompose(slow_xf_fullextrema, Map() do ((argmin, min), (argmax, max))
    (argmin, argmax)
end)

@testset "slow compilation" begin
    @test foldl(right, slow_xf_fullextrema, [1.0, 3.0, -1.0, missing, 2.0]) ===
        ((3, -1.0), (2, 3.0))

    @test foldl(right, slow_xf_argextrema, [1.0, 3.0, -1.0, missing, 2.0]) ===
        (3, 2)

    # Excluding `missing` from the input vector seems to slow down
    # compilation a lot.
    slow_test("slow compilation test with xf_fullextrema", 20) do
        @test foldl(right, slow_xf_fullextrema, [1.0, 3.0, -1.0, 2.0]) ==
            ((3, -1.0), (2, 3.0))
    end
    slow_test("slow compilation test with xf_argextrema", 20) do
        @test foldl(right, slow_xf_argextrema, [1.0, 3.0, -1.0, 2.0]) ==
            (3, 2)
    end
end

end  # module


text:
# fence

export ZeFence

mutable struct ZeFence
    handle::ze_fence_handle_t
    queue::ZeCommandQueue

    function ZeFence(queue)
        desc_ref = Ref(ze_fence_desc_t())
        handle_ref = Ref{ze_fence_handle_t}()
        zeFenceCreate(queue, desc_ref, handle_ref)
        obj = new(handle_ref[], queue)
        finalizer(obj) do obj
            zeFenceDestroy(obj)
        end
        obj
    end
end

Base.unsafe_convert(::Type{ze_fence_handle_t}, fence::ZeFence) = fence.handle

Base.wait(fence::ZeFence, timeout::Number=typemax(UInt64)) =
    zeFenceHostSynchronize(fence, timeout)

Base.reset(fence::ZeFence) = zeFenceReset(fence)

function Base.isdone(fence::ZeFence)
    res = unsafe_zeFenceQueryStatus(fence)
    if res == RESULT_NOT_READY
        return false
    elseif res == RESULT_SUCCESS
        return true
    else
        throw_api_error(res)
    end
end


text:
# operators on Python objects

# binary operators
import Base: +,-,*,/,//,%,&,|,^,<<,>>
import Compat: ⊻
for (op,py) in ((:+,:PyNumber_Add), (:-,:PyNumber_Subtract), (:*,:PyNumber_Multiply),
                (:/,:PyNumber_TrueDivide), (:%,:PyNumber_Remainder),
                (:&,:PyNumber_And), (:|,:PyNumber_Or),
                (:<<,:PyNumber_Lshift), (:>>,:PyNumber_Rshift), (:⊻,:PyNumber_Xor))
    qpy = QuoteNode(py)
    @eval $op(a::PyObject, b) =
        PyObject(@pycheckn ccall((@pysym $qpy), PyPtr, (PyPtr, PyPtr), a,PyObject(b)))
end
^(a::PyObject, b) = PyObject(@pycheckn ccall((@pysym :PyNumber_Power), PyPtr, (PyPtr, PyPtr, PyPtr), a, PyObject(b), pynothing[]))
^(a::PyObject, b::Integer) = PyObject(@pycheckn ccall((@pysym :PyNumber_Power), PyPtr, (PyPtr, PyPtr, PyPtr), a, PyObject(b), pynothing[]))

if VERSION >= v"0.6.0-dev.1632" # julia#17623
    # .+= etcetera map to in-place Python operations
    for (op,py) in ((:+,:PyNumber_InPlaceAdd), (:-,:PyNumber_InPlaceSubtract), (:*,:PyNumber_InPlaceMultiply),
                    (:/,:PyNumber_InPlaceTrueDivide), (:%,:PyNumber_InPlaceRemainder),
                    (:&,:PyNumber_InPlaceAnd), (:|,:PyNumber_InPlaceOr),
                    (:<<,:PyNumber_InPlaceLshift), (:>>,:PyNumber_InPlaceRshift), (:⊻,:PyNumber_InPlaceXor))
        qpy = QuoteNode(py)
        @eval function Base.broadcast!(::typeof($op), a::PyObject, a′::PyObject, b)
            a.o == a′.o || throw(MethodError(broadcast!, ($op, a, a', b)))
            PyObject(@pycheckn ccall((@pysym $qpy), PyPtr, (PyPtr, PyPtr), a,PyObject(b)))
        end
    end
end

# unary operators and functions
import Base: abs,~
for (op,py) in ((:+,:PyNumber_Positive), (:-,:PyNumber_Negative),
                (:abs,:PyNumber_Absolute), (:~, :PyNumber_Invert))
    qpy = QuoteNode(py)
    @eval $op(a::PyObject) = PyObject(@pycheckn ccall((@pysym $qpy), PyPtr, (PyPtr,), a))
end

#########################################################################
# PyObject equality and other comparisons

# rich comparison opcodes from Python's object.h:
const Py_LT = Cint(0)
const Py_LE = Cint(1)
const Py_EQ = Cint(2)
const Py_NE = Cint(3)
const Py_GT = Cint(4)
const Py_GE = Cint(5)

import Base: <, <=, ==, !=, >, >=, isequal, isless
for (op,py) in ((:<, Py_LT), (:<=, Py_LE), (:(==), Py_EQ), (:!=, Py_NE),
                (:>, Py_GT), (:>=, Py_GE), (:isequal, Py_EQ), (:isless, Py_LT))
    @eval function $op(o1::PyObject, o2::PyObject)
        if o1.o == C_NULL || o2.o == C_NULL
            return $(py==Py_EQ || py==Py_NE || op==:isless ? :($op(o1.o, o2.o)) : false)
        elseif is_pyjlwrap(o1) && is_pyjlwrap(o2)
            return $op(unsafe_pyjlwrap_to_objref(o1.o),
                       unsafe_pyjlwrap_to_objref(o2.o))
        else
            if $(op == :isless || op == :isequal)
                return Bool(@pycheckz ccall((@pysym :PyObject_RichCompareBool), Cint,
                                            (PyPtr, PyPtr, Cint), o1, o2, $py))
            else # other operations may return a PyObject
                return PyAny(PyObject(@pycheckn ccall((@pysym :PyObject_RichCompare), PyPtr,
                                                      (PyPtr, PyPtr, Cint), o1, o2, $py)))
            end
        end
    end
    if op != :isequal
        @eval begin
            $op(o1::PyObject, o2::Any) = $op(o1, PyObject(o2))
            $op(o1::Any, o2::PyObject) = $op(PyObject(o1), o2)
        end
    end
end
# default to false since hash(x) != hash(PyObject(x)) in general
isequal(o1::PyObject, o2::Any) = o1.o != C_NULL && is_pyjlwrap(o1) ? isequal(unsafe_pyjlwrap_to_objref(o1.o), o2) : false
isequal(o1::Any, o2::PyObject) = isequal(o2, o1)


text:
using MultiDimDictionaries
using Documenter

DocMeta.setdocmeta!(
  MultiDimDictionaries, :DocTestSetup, :(using MultiDimDictionaries); recursive=true
)

makedocs(;
  modules=[MultiDimDictionaries],
  authors="Matthew Fishman <mfishman@flatironinstitute.org> and contributors",
  repo="https://github.com/mtfishman/MultiDimDictionaries.jl/blob/{commit}{path}#{line}",
  sitename="MultiDimDictionaries.jl",
  format=Documenter.HTML(;
    prettyurls=get(ENV, "CI", "false") == "true",
    canonical="https://mtfishman.github.io/MultiDimDictionaries.jl",
    assets=String[],
  ),
  pages=["Home" => "index.md"],
)

deploydocs(; repo="github.com/mtfishman/MultiDimDictionaries.jl", devbranch="main")


text:
########################### POMDPModel Implementation #################
"""
Rules
1) All POMDP functions should not change the input parameter(s) except DP object !!!
2) All calls to search functions(eg. findfirst()) should be wrapped by "try...catch" block
"""

function POMDPs.initialstate_distribution(DP::DrivePOMDP)
    #println("Distribution Initialization")
    PD = zeros(length(DP.SSpace))
    weight = 1.5
    ss_init = deepcopy(DP.SsInit)
    for ri in DP.rV
        ss_init.Other.r = ri
        index_init = 0
        try
            index_init = findfirst(x->x==ss_init, DP.SSpace)
        catch
            error("initial state not found in Statespace")
        end
        fk1 = weight*abs(ss_init.Other.v - DP.Routes[ri].Vref[1])
        Pfk1 = cdf(Normal(0.0, 2.0), -fk1)
        PD[index_init] = Pfk1
    end
    normalize!(PD, 1)
    return SparseCat(DP.SSpace, PD)
end

POMDPs.discount(DP::DrivePOMDP) = DP.discount_factor

function POMDPs.isterminal(DP::DrivePOMDP, Ss::Sts)
    result = Ss.Ego.s >= DP.sV[end] || Ss.Other.s >= DP.sV[end]
    #if result
    #    println("enter terminal state")
    #end
    return result
end

function Simulator(DP::DrivePOMDP, up::Updater, policy::Policy, rng::AbstractRNG)
    StsVec = Vector{Sts}()
    ObsVec = Vector{CarOb}()
    ActVec = Vector{Symbol}()
    AccMat = Vector{Vector{Float64}}()
    b = initialize_belief(up, initialstate_distribution(DP))
    BeliefVec = [b,]
    r_total = 0.0
    d = 1.0
    s = deepcopy(initialstate(DP, rng))
    #s = deepcopy(rand(rng, b))
    i = 1
    while !isterminal(DP, s)
        println("-------- Step: $i --------")
        push!(StsVec, s)
        Act_ego = action(policy, b) # b will be changed in every step
        push!(ActVec, Act_ego)
        #sp = rand(rng, transition(DP, s, a))
        sp_cat = transition(DP, s, Act_ego)

        sp_p, spi = findmax(sp_cat.probs)
        sp = sp_cat.vals[spi]
        #sp = rand(rng, sp_cat)
        #acc_ego = (sp.Ego.v^2 - s.Ego.v^2)/(2*(sp.Ego.s - s.Ego.s))
        acc_k = (sp.Other.v^2 - s.Other.v^2)/(2*(sp.Other.s - s.Other.s))
        accVec = IDMtransit(DP, s, Act_ego, acc_k).accs
        push!(AccMat, accVec)

        r = reward(DP, s, Act_ego, sp)
        r_total += d*r

        # sp_real is only for observation generation
        sp_real = deepcopy(sp)
        sp_real.Other.r = DP.SsInit.Other.r
        #o = rand(rng, observation(DP, sp_real))
        ob_cat = observation(DP, sp_real)
        #println("--- show ob distribution ---")
        #show_cat(ob_cat, 0x003)
        #println("--- -------------------- ---")
        ob_p, obi = findmax(ob_cat.probs)
        o = ob_cat.vals[obi]
        push!(ObsVec, o)

        @show s
        @show Act_ego#, acc_ego
        @show o
        println("realtime reward: $r")
        @show r_total

        d *= discount(DP)
        b = deepcopy(update(up, b, Act_ego, o))
        push!(BeliefVec, b)
        probmax, probi = findmax(b.b)
        s = deepcopy(b.state_list[probi])
        #s = deepcopy(rand(rng, b))
        i += 1
    end
    return (StsVec, ObsVec, BeliefVec, ActVec, AccMat)
end

function update(bu::DiscreteUpdater, b::DiscreteBelief, a::Symbol, o::CarOb)
    #println("----- update -----")
    pomdp = b.pomdp
    state_space = b.state_list
    bp = zeros(length(state_space))
    for spi = 1:length(state_space)
        sp = state_space[spi]
        od = observation(pomdp, sp)
        po = pdf(od, o)
        if po > 1e-3
            b_sum = 0.0
            for si = 1:length(state_space)
                if b.b[si] > 1e-2
                     s = state_space[si]
                     td = transition(pomdp, s, a)
                     pp = pdf(td, sp)
                     b_sum += pp * b.b[si]
                 end
             end
             bp[spi] = po * b_sum
         end
    end
    bp_sum = sum(bp)
    if bp_sum == 0.0
        error("""
              Failed discrete belief update: new probabilities sum to zero.

              a = $a
              o = $o

              Failed discrete belief update: new probabilities sum to zero.
              """)
    else
        for i = 1:length(bp); bp[i] /= bp_sum; end
    end
    return DiscreteBelief(pomdp, b.state_list, bp)
end

update(bu::DiscreteUpdater, b::Any, a::Symbol, o::CarOb) = update(bu, initialize_belief(bu, b), a::Symbol, o::CarOb)

function update_info(bu::DiscreteUpdater, b::Any, a::Symbol, o::CarOb)
    return update(bu, b, a, o), nothing
end

function show_cat(cat::SparseCat, num::UInt16)
    cat_dict = Dict(zip(cat.vals, cat.probs))
    println(sort(collect(cat_dict), by = x->x[2])[end-num:end])
end

function show_DB(DB::DiscreteBelief{DrivePOMDP, Sts}, num::UInt16)
    DB_dict = Dict(zip(DB.state_list, DB.b))
    println(sort(collect(DB_dict), by = x->x[2])[end-num:end])
end


text:
struct SymmetriesGraph
    graph::SimpleGraph{Int64}
    node_lookup
    reverse_node_lookup
end

"""
    random_symmetric_2players_game(dist::Distributions.Sampleable,p1_size::Int,p2_size::Int)

Returns random symmetric payoff matrices for 2 players with given number of actions

**Input parameters**
* `dist::Distributions.Sampleable` - distribution from which payoffs are sampled
* `p_size::Int` - number of actions of a player
"""
function random_symmetric_2players_game(dist::Distributions.Sampleable,
                               p_size::Int)
    random_data = rand(dist, p_size, p_size)
    data = [random_data, transpose(random_data)]
    return Dict("player"*string(i)=>data[i] for i in 1:2)
end

"""
    find_symmetric_nash_equilibrium_2players_game(game::Dict{String,<:AbstractArray}, s::Array{SymPy.Sym,1})

Finds necessary values to find symmetric Nash equilibrium

**Input parameters**
* `game::Dict{String,<:AbstractArray}` - dictionary of players and their payoff matrices
* `s::Array{SymPy.Sym,1}` - collection of actions probabilities
"""
function find_symmetric_nash_equilibrium_2players_game(game::Dict{String,<:AbstractArray},
               s::Array{SymPy.Sym,1})
    n = size(game["player1"])[1]
    id_m = Matrix(1I, n, n)
    res = 0
    for i in 1:n
        res = res + max(get_payoff(game, [map(x->sympify(x), id_m[i, :]), s])["player1"] - get_payoff(game, [s, s])["player1"], 0)^2
    end
    return find_zeros(res, 0, 1)
end

"""
    create_symmetries_graph(actions_no_vector::Array{Int64})

Return graph of needed symmetries in the game

**Input parameters**
* `actions_no_vector::Array{Int64}` - array of number of actions of consecutive players
"""
function create_symmetries_graph(actions_no_vector::Array{Int64})
    payout_tensor = [()]
    for k in actions_no_vector
        payout_tensor = collect(Iterators.flatten([[(j...,i) for i in 1:k] for j in payout_tensor]))
    end
    payout_tensor = collect(Iterators.flatten([[(j,i) for i in 1:length(actions_no_vector)] for j in payout_tensor]))
    @info "Created payout tensor: $(payout_tensor)"

    p = permutations(collect(1:length(actions_no_vector)))
    equalities = unique(collect(Iterators.flatten([[(b, (b[1][i], i[b[2]])) for i in p] for b in payout_tensor])))
    equalities = filter(x -> x[1]!=x[2], equalities)
    G₁ = Graph(length(payout_tensor))
    node_lookup = Dict(payout_tensor[i] => i for i in 1:length(payout_tensor))
    for i in equalities
        add_edge!(G₁, node_lookup[i[1]], node_lookup[i[2]])
    end
    return SymmetriesGraph(G₁, node_lookup, Dict(value => key for (key, value) in node_lookup))
end

"""
    check_equality_condition(g::SymmetriesGraph, payout_1, payout_2)

Checks if there needs to be an equality between two payouts

**Input parameters**
* `g::SymmetriesGraph` - symmetries graph
* `payout_1` - first payout
* `payout_2` - second payout
"""
function check_equality_condition(g::SymmetriesGraph, payout_1, payout_2)
    return has_path(g.graph, g.node_lookup[payout_1], g.node_lookup[payout_2])
end

"""
    find_all_equalities(g::SymmetriesGraph)

Finds all payout tuples, that need to be equal

**Input parameters**
* `g::SymmetriesGraph` - symmetries graph
"""
function find_all_equalities(g::SymmetriesGraph)
    tmp = Dict{Int64,Vector{Tuple{Int64, Int64}}}()
    Threads.@threads for i in vertices(g.graph)
        tmp[i] = collect(unique(filter(x->x[2]>x[1],map(x->(dst(x),i), edges(dfs_tree(g.graph, i))))))
    end
    return map(x -> (g.reverse_node_lookup[x[1]], g.reverse_node_lookup[x[2]]), collect(Iterators.flatten(values(tmp))))
end


text:
using ValidatedNumerics

"""Macro to make a version of a multidimensional function that acts on
an `IntervalBox` and returns an `IntervalBox`.
Both the original n-argument function and the `IntervalBox` version are defined.

Example:

    @intervalbox f(x, y) = (x + y, x - y)

    X = IntervalBox(1..1, 2..2)
    f(X)

(No significant error checking is performed!)
"""

macro intervalbox(ex)
    # @show ex
    # @show ex.head
    if ex.head != :(=)
        throw(ArgumentError("Not a function definition."))
    end

    if ex.args[1].head != :call
        throw(ArgumentError("Not a function definition."))
    end

    f = ex.args[1].args[1]  # function name
    f = esc(f)
    ex.args[1].args[1] = f  # escape the function name in the original code

    new_ex = Expr(:block)

    push!(new_ex.args, ex)  # the function call

    push!(new_ex.args,  :( ($f)(X::IntervalBox) = IntervalBox( $f(X...)...) ) )

    #@show new_ex
    new_ex
end


text:
module MathematicaPalette

using Colors: @colorant_str
using Gadfly: Theme, get_stroke_vector
using Measures: pt

export MathematicaRed, MathematicaYellow, MathematicaOrange, MathematicaBrick
export MathematicaLightGreen, MathematicaGreen, MathematicaDarkGreen
export MathematicaLightTeal, MathematicaTeal, MathematicaDarkTeal
export MathematicaLightBlue, MathematicaBlue, MathematicaDarkBlue
export MathematicaLightPurple, MathematicaPurple, MathematicaDarkPurple
export MathematicaBeige, MathematicaTan, MathematicaGrey
export MathematicaRedTheme, MathematicaGreenTheme, MathematicaTealTheme
export MathematicaBlueTheme, MathematicaPurpleTheme

const MathematicaRed = colorant"#e70033"
const MathematicaYellow = colorant"#ffcb00"
const MathematicaOrange = colorant"#ef8200"
const MathematicaBrick = colorant"#c05131"
const MathematicaLightGreen = colorant"#77b800"
const MathematicaGreen = colorant"#003a3d"
const MathematicaDarkGreen = colorant"#00694e"
const MathematicaLightTeal = colorant"#30cdd7"
const MathematicaTeal = colorant"#0098aa"
const MathematicaDarkTeal = colorant"#006784"
const MathematicaLightBlue = colorant"#34b6e4"
const MathematicaBlue = colorant"#0063be"
const MathematicaDarkBlue = colorant"#002e5f"
const MathematicaLightPurple = colorant"#a5a4df"
const MathematicaPurple = colorant"#651f76"
const MathematicaDarkPurple = colorant"#1e0576"
const MathematicaBeige = colorant"#d7d3c8"
const MathematicaTan = colorant"#c7be71"
const MathematicaGrey = colorant"#6c6f70"

const _default_theme = Theme(
  # If the color aesthetic is not mapped to anything, this is the color that
  # is used.
  default_color=MathematicaRed,

  # Default size when the size aesthetic is not mapped.
  default_point_size=3pt,

  # Width of lines in the line geometry.
  line_width=2pt,

  # type of dash style (a Compose.StrokeDash object which takes a vector of sold/missing/solid/missing/...
   # lengths which are applied cyclically)
  line_style=get_stroke_vector(:solid),

  # Background color of the plot.
  panel_fill=MathematicaBeige,

  # Border color of the plot panel.
  panel_stroke=nothing,

  # Opacity of the plot background panel.
  panel_opacity=1.0,

  # Background of the entire plot
  background_color=nothing,

  # Padding around the entire plot
  plot_padding=6pt,

  # Grid line color.
  grid_color=MathematicaGrey,
  grid_strokedash=get_stroke_vector(:solid),

  # Grid lines for focused item.
  grid_color_focused=MathematicaGrey,

  # Width of grid lines
  grid_line_width=0.5pt,

  # Font name, size, and color used for tick labels, entries in keys, etc.
  minor_label_font="'Arial','Liberation Sans',sans-serif",
  minor_label_font_size=8pt,
  minor_label_color=colorant"black",

  # Font name, size and color used for axis labels, key title, etc.
  major_label_font="'Arial','Liberation Sans',sans-serif",
  major_label_font_size=11pt,
  major_label_color=colorant"black",

  # Font name, size and color used for labels on plot elements.
  point_label_font="'Arial','Liberation Sans',sans-serif",
  point_label_font_size=8pt,
  point_label_color=colorant"black",

  # Font name, size and color used for key titles
  key_title_font="'Arial','Liberation Sans',sans-serif",
  key_title_font_size=11pt,
  key_title_color=colorant"black",

  # Font name, size and color used for key entries.
  key_label_font="'Arial','Liberation Sans',sans-serif",
  key_label_font_size=8pt,
  key_label_color=colorant"black",

  # How many gradations to show in a continuous color key.
  key_color_gradations=10,

  # Spacing between bars for Geom.bar.
  bar_spacing=0pt, #-0.05mm?

  # Spacing between boxplots in Geom.boxplot.
  boxplot_spacing=3pt,

  # Length of caps on error bars
  errorbar_cap_length=6pt,

  # Lines are drawn in a slightly different color than fills, e.g. to
  # differentiate histogram bars from error bars.
  #stroke_color=default_stroke_color,

  # Points, etc, are highlighted by stroking in slightly different color. This
  # is the stroke width.
  highlight_width=0.5pt,

  # A function mapping fill color to stoke color for highlights.
  #discrete_highlight_color=default_discrete_highlight_color
  #continuous_highlight_color=default_continuous_highlight_color,

  # A function mapping fill color to a duller background fill color. Used for
  # Geom.ribbon in particular so lines stand out against it.
  #lowlight_color=default_lowlight_color,

  # Opacity of geometry filled with lowlight_color
  lowlight_opacity=0.6,

  # A function mapping base fill color to the color of the median marker in a
  # boxplot.
  #middle_color=default_middle_color,

  # Width of the middle line in a boxplot.
  middle_width=1pt,

  # Horizontal position of the title of color key guides. One of :left,
  # :right, :center.
  guide_title_position=:left,

  # Shape used in color keys for color swatches. Either :square or :circle.
  colorkey_swatch_shape=:circle,

  # One of :left, :right, :top, :bottom, :none determining where color keys
  # and the like should be placed.
  key_position=:right,

  # True if bars in bar plots should be stroked. Stroke color is
  bar_highlight=nothing,

  # Symbol forms used for the shape aesthetic
  #shapes=[circle, square, diamond, cross, xcross, utriangle, dtriangle, star1, star2, hexagon, octagon]

  # Qua?  Something to do with the minimum height of things and clipping...
  rug_size=6pt

  # TODO: This stuff is too incomprehensible to be in theme, I think. Put it
  # somewhere else.

  # Number of annealing iterations.
  #label_placement_iterations=1000,

  # Penalty for a label not being contained within the plot frame.
  #label_out_of_bounds_penalty=10.0,

  # Penalty for making a label hidden to avoid overlaps.
  #label_hidden_penalty=0.5,

  # Probability of proposing a visibility flip during label layout.
  #label_visibility_flip_pr=0.2,

  # Number of columns in key
  #key_max_columns=4

)
const MathematicaRedTheme = Theme(_default_theme)
const MathematicaGreenTheme = Theme(_default_theme)
MathematicaGreenTheme.default_color=MathematicaGreen
const MathematicaTealTheme = Theme(_default_theme)
MathematicaTealTheme.default_color=MathematicaTeal
const MathematicaBlueTheme = Theme(_default_theme)
MathematicaBlueTheme.default_color=MathematicaBlue
const MathematicaPurpleTheme = Theme(_default_theme)
MathematicaPurpleTheme.default_color=MathematicaPurple

end # module


text:
@with_kw struct Catch
    γ::Float64=0.9
end

function DiscretePOMDP(mdp::Catch; γ::Float64=mdp.γ)
    Θ = [20,40,60,80] # proficiencies
    𝒜 = collect(10:10:100) # throw distances

    nS = length(Θ)
    nA = length(𝒜)
    nO = 2 # catch or not

    T = zeros(nS, nA, nS)
    R = Array{Float64}(undef, nS, nA)
    O = Array{Float64}(undef, nA, nS, nO)

    o_catch = 1
    o_drop = 2

    prob_catch(d,θ) = 1 - 1/(1+exp(-(d-θ)/15))

    # Transition dynamics are 100% stationary.
    for si in 1:nS
        for ai in 1:nA
            T[si, ai, si] = 1.0
        end
    end

    # Reward equal to distance caught
    for (si,θ) in enumerate(Θ)
        for (ai,d) in enumerate(𝒜)
            R[si,ai] = d*prob_catch(d,θ) # distance caught times prob of catch
        end
    end

    # Observation is based on whether we caught or not.
    for (ai,d) in enumerate(𝒜)
        for (si′,θ) in enumerate(Θ)
            O[ai,si′,o_catch] = prob_catch(d,θ)
            O[ai,si′,o_drop] = 1 - O[ai,si′,o_catch]
        end
    end

    return DiscretePOMDP(T, R, O, γ)
end

function POMDP(mdp::Catch; γ::Float64=mdp.γ)
    Θ = [20,40,60,80] # proficiencies
    𝒜 = collect(10:10:100) # throw distances

    nS = length(Θ)
    nA = length(𝒜)
    nO = 2 # catch or not

    T = zeros(nS, nA, nS)
    R = Array{Float64}(undef, nS, nA)
    O = Array{Float64}(undef, nA, nS, nO)

    o_catch = 1
    o_drop = 2

    prob_catch(d,θ) = 1 - 1/(1+exp(-(d-θ)/15))

    # Transition dynamics are 100% stationary.
    for si in 1:nS
        for ai in 1:nA
            T[si, ai, si] = 1.0
        end
    end

    # Reward equal to distance caught
    for (si,θ) in enumerate(Θ)
        for (ai,d) in enumerate(𝒜)
            R[si,ai] = d*prob_catch(d,θ) # distance caught times prob of catch
        end
    end

    # Observation is based on whether we caught or not.
    for (ai,d) in enumerate(𝒜)
        for (si′,θ) in enumerate(Θ)
            O[ai,si′,o_catch] = prob_catch(d,θ)
            O[ai,si′,o_drop] = 1 - O[ai,si′,o_catch]
        end
    end

    return POMDP(DiscretePOMDP(T, R, O, γ))
end

# const Catch = generate_catch_pomdp(0.9)


text:
# This file is a part of JuliaFEM.
# License is MIT: see https://github.com/JuliaFEM/FEMBase.jl/blob/master/LICENSE

using FEMBase
using Test

# Time interpolation of fields

element = Element(Seg2, [1, 2])
update!(element, "force", 1.0 => 15.0)
update!(element, "force", 2.0 => 30.0)
@test isapprox(element("force", 1.0), 15.0)
@test isapprox(element("force", 1.2), 18.0)
@test isapprox(element("force", 1.6), 24.0)
@test isapprox(element("force", 2.0), 30.0)

update!(element, "temperature", 0.0 => (1.0, 3.0))
update!(element, "temperature", 1.0 => (2.0, 14.0))
@test isapprox(element("temperature", (0.0,), 0.0), 2.0)
@test isapprox(element("temperature", (0.0,), 0.3), 3.8)
@test isapprox(element("temperature", (0.0,), 1.0), 8.0)


text:
#
# Copyright (c) 2021 Tobias Thummerer, Lars Mikelsons, Josef Kircher
# Licensed under the MIT license. See LICENSE file in the project root for details.
#

###############
# Prepare FMU #
###############

pathToFMU = joinpath(dirname(@__FILE__), "..", "model", ENV["EXPORTINGTOOL"], "IO.fmu")

myFMU = fmiLoad(pathToFMU)
comp = fmiInstantiate!(myFMU; loggingOn=false)
@test comp != 0

# choose FMU or FMUComponent
fmuStruct = nothing
envFMUSTRUCT = ENV["FMUSTRUCT"]
if envFMUSTRUCT == "FMU"
    fmuStruct = myFMU
elseif envFMUSTRUCT == "FMUCOMPONENT"
    fmuStruct = comp
end
@assert fmuStruct != nothing "Unknown fmuStruct, environment variable `FMUSTRUCT` = `$envFMUSTRUCT`"

@test fmiSetupExperiment(fmuStruct, 0.0) == 0

@test fmiEnterInitializationMode(fmuStruct) == 0

realValueReferences = ["p_real", "u_real"]
integerValueReferences = ["p_integer", "u_integer"]
booleanValueReferences = ["p_boolean", "u_boolean"]
stringValueReferences = ["p_string", "p_string"]

#########################
# Testing Single Values #
#########################

rndReal = 100 * rand()
rndInteger = round(Integer, 100 * rand())
rndBoolean = rand() > 0.5
rndString = Random.randstring(12)

cacheReal = 0.0
cacheInteger = 0
cacheBoolean = false
cacheString = ""

@test fmiSetReal(fmuStruct, realValueReferences[1], rndReal) == 0
@test fmiGetReal(fmuStruct, realValueReferences[1]) == rndReal
@test fmiSetReal(fmuStruct, realValueReferences[1], -rndReal) == 0
@test fmiGetReal(fmuStruct, realValueReferences[1]) == -rndReal

@test fmiSetInteger(fmuStruct, integerValueReferences[1], rndInteger) == 0
@test fmiGetInteger(fmuStruct, integerValueReferences[1]) == rndInteger
@test fmiSetInteger(fmuStruct, integerValueReferences[1], -rndInteger) == 0
@test fmiGetInteger(fmuStruct, integerValueReferences[1]) == -rndInteger

@test fmiSetBoolean(fmuStruct, booleanValueReferences[1], rndBoolean) == 0
@test fmiGetBoolean(fmuStruct, booleanValueReferences[1]) == rndBoolean
@test fmiSetBoolean(fmuStruct, booleanValueReferences[1], !rndBoolean) == 0
@test fmiGetBoolean(fmuStruct, booleanValueReferences[1]) == !rndBoolean

@test fmiSetString(fmuStruct, stringValueReferences[1], rndString) == 0
@test fmiGetString(fmuStruct, stringValueReferences[1]) == rndString

##################
# Testing Arrays #
##################

rndReal = [100 * rand(), 100 * rand()]
rndInteger = [round(Integer, 100 * rand()), round(Integer, 100 * rand())]
rndBoolean = [(rand() > 0.5), (rand() > 0.5)]
tmp = Random.randstring(8)
rndString = [tmp, tmp]

cacheReal = [0.0, 0.0]
cacheInteger =  [FMI.fmi2Integer(0), FMI.fmi2Integer(0)]
cacheBoolean = [FMI.fmi2Boolean(false), FMI.fmi2Boolean(false)]
cacheString = [FMI.fmi2String(""), FMI.fmi2String("")]

@test fmiSetReal(fmuStruct, realValueReferences, rndReal) == 0
@test fmiGetReal(fmuStruct, realValueReferences) == rndReal
fmiGetReal!(fmuStruct, realValueReferences, cacheReal)
@test cacheReal == rndReal
@test fmiSetReal(fmuStruct, realValueReferences, -rndReal) == 0
@test fmiGetReal(fmuStruct, realValueReferences) == -rndReal
fmiGetReal!(fmuStruct, realValueReferences, cacheReal)
@test cacheReal == -rndReal

@test fmiSetInteger(fmuStruct, integerValueReferences, rndInteger) == 0
@test fmiGetInteger(fmuStruct, integerValueReferences) == rndInteger
fmiGetInteger!(fmuStruct, integerValueReferences, cacheInteger)
@test cacheInteger == rndInteger
@test fmiSetInteger(fmuStruct, integerValueReferences, -rndInteger) == 0
@test fmiGetInteger(fmuStruct, integerValueReferences) == -rndInteger
fmiGetInteger!(fmuStruct, integerValueReferences, cacheInteger)
@test cacheInteger == -rndInteger

@test fmiSetBoolean(fmuStruct, booleanValueReferences, rndBoolean) == 0
@test fmiGetBoolean(fmuStruct, booleanValueReferences) == rndBoolean
fmiGetBoolean!(fmuStruct, booleanValueReferences, cacheBoolean)
@test cacheBoolean == rndBoolean
not_rndBoolean = collect(!b for b in rndBoolean)
@test fmiSetBoolean(fmuStruct, booleanValueReferences, not_rndBoolean) == 0
@test fmiGetBoolean(fmuStruct, booleanValueReferences) == not_rndBoolean
fmiGetBoolean!(fmuStruct, booleanValueReferences, cacheBoolean)
@test cacheBoolean == not_rndBoolean

@test fmiSetString(fmuStruct, stringValueReferences, rndString) == 0
@test fmiGetString(fmuStruct, stringValueReferences) == rndString
fmiGetString!(fmuStruct, stringValueReferences, cacheString)
@test cacheString == rndString

############
# Clean up #
############

@test fmiExitInitializationMode(fmuStruct) == 0

fmiUnload(myFMU)


text:
using Distributions
using Mjolnir: AType, Const, Basic
import Mjolnir: abstract

abstract(::Basic, ::AType{typeof(rand)}) = Float64
abstract(::Basic, ::AType{typeof(randn)}) = Float64
abstract(::Basic, ::AType{typeof(rand)}, ::AType{<:Type{Bool}}) where T = Bool

abstract(::Basic, ::AType{typeof(rand)}, T::AType{<:Distribution}) =
  Core.Compiler.return_type(rand, Tuple{Mjolnir.widen(T)})

abstract(::Basic, ::AType{Type{Bernoulli}}, ::AType{T}) where T<:AbstractFloat = Bernoulli{Float64}


text:
@inline function ExaTronKernels.dscal(n::Int,da::Float64,dx::ROCDeviceArray{Float64,1},incx::Int)
    tx = workitemIdx().x

    # Ignore incx for now.
    if tx <= n
        @inbounds dx[tx] = da*dx[tx]
    end
    AMDGPU.sync_workgroup()

    return
end


text:
using FSimBase
using DifferentialEquations

using ComponentArrays

function main()
    state0 = [1, 2]
    p = 1
    @Loggable function dynamics!(dx, x, p, t)
        @log t
        @log x
        dx .= -p.*x
    end
    prob, df = sim(state0, dynamics!, p;
                   solver=Tsit5(),
                   tf=10.0,
                  )
    df
end


text:
using SimulatedNeuralMoments, Statistics, DelimitedFiles
results = readdlm("mcresultsCUE.txt")
sofar = 500
println("__________ replication: ", sofar, "_______________")
clabels = ["99%", "95%", "90%"]
prettyprint(reshape(mean(results[1:sofar,6:end],dims=1),5,3),clabels)
dstats(results[1:sofar,1:5])

max_stars_repo_name: mcreel/ILSNM

max_issues_repo_name: mcreel/ILSNM

max_forks_repo_name: mcreel/ILSNM


text:
################################################################################
## Copyright 2016. Juri Hinz and Jeremy Yee.
## Stochastic grid
################################################################################

## Stochastic grid type definition

immutable SGrid

    ## Members
    snum::Int64 # state size
    gnum::Int64 # number of grid points
    maxIter::Int64 # max iterations used in the kmeans clustering
    grid::Array{Float64, 2} # sample paths

    function SGrid(paths::Array{Float64, 3}, gnum::Int64, maxIter = 100)

        ## Extract parameters
        snum = size(paths)[3];
        tnum = size(paths)[1];
        pnum = size(paths)[2];

        ## Collect states visited
        states = Matrix{Float64}(snum, tnum * pnum);
        i = 1;
        for t = 1:tnum
            for p = 1:pnum
                states[:, i] = paths[t,p,:]
                i = i + 1;
            end
        end

        ## apply kmeans clustering
        clusters = kmeans(states, gnum, maxiter = maxIter)

        return new(snum, snum, maxIter, transpose(clusters.centers))

    end

end


text:
"""$(TYPEDEF)
Solver options for the augmented Lagrangian solver.
$(FIELDS)
"""
@with_kw mutable struct AugmentedLagrangianSolverOptions{T} <: AbstractSolverOptions{T}
    "Print summary at each iteration."
    verbose::Bool=false

    "unconstrained solver options."
    opts_uncon::AbstractSolverOptions{T} = iLQRSolverOptions{T}()

    "dJ < ϵ, cost convergence criteria for unconstrained solve or to enter outerloop for constrained solve."
    cost_tolerance::T = 1.0e-4

    "dJ < ϵ_int, intermediate cost convergence criteria to enter outerloop of constrained solve."
    cost_tolerance_intermediate::T = 1.0e-3

    "gradient_norm < ϵ, gradient norm convergence criteria."
    gradient_norm_tolerance::T = 1.0e-5

    "gradient_norm_int < ϵ, gradient norm intermediate convergence criteria."
    gradient_norm_tolerance_intermediate::T = 1.0e-5

    "max(constraint) < ϵ, constraint convergence criteria."
    constraint_tolerance::T = 1.0e-3

    "max(constraint) < ϵ_int, intermediate constraint convergence criteria."
    constraint_tolerance_intermediate::T = 1.0e-3

    "maximum outerloop updates."
    iterations::Int = 30

    "minimum Lagrange multiplier."
    dual_min::T = -1.0e8

    "maximum Lagrange multiplier."
    dual_max::T = 1.0e8

    "maximum penalty term."
    penalty_max::T = 1.0e8

    "initial penalty term."
    penalty_initial::T = 1.0

    "penalty update multiplier; penalty_scaling > 0."
    penalty_scaling::T = 10.0

    "penalty update multiplier when μ should not be update, typically 1.0 (or 1.0 + ϵ)."
    penalty_scaling_no::T = 1.0

    "ratio of current constraint to previous constraint violation; 0 < constraint_decrease_ratio < 1."
    constraint_decrease_ratio::T = 0.25

    "type of outer loop update (default, feedback)."
    outer_loop_update_type::Symbol = :default

    "numerical tolerance for constraint violation."
    active_constraint_tolerance::T = 0.0

    "terminal solve when maximum penalty is reached."
    kickout_max_penalty::Bool = false

end

@doc raw""" ```julia
struct AugmentedLagrangianSolver <: TrajectoryOptimization.AbstractSolver{T}
```
Augmented Lagrangian (AL) is a standard tool for constrained optimization. For a trajectory optimization problem of the form:
```math
\begin{equation*}
\begin{aligned}
  \min_{x_{0:N},u_{0:N-1}} \quad & \ell_f(x_N) + \sum_{k=0}^{N-1} \ell_k(x_k, u_k, dt) \\
  \textrm{s.t.}            \quad & x_{k+1} = f(x_k, u_k), \\
                                 & g_k(x_k,u_k) \leq 0, \\
                                 & h_k(x_k,u_k) = 0.
\end{aligned}
\end{equation*}
```
AL methods form the following augmented Lagrangian function:
```math
\begin{align*}
    \ell_f(x_N) + &λ_N^T c_N(x_N) + c_N(x_N)^T I_{\mu_N} c_N(x_N) \\
           & + \sum_{k=0}^{N-1} \ell_k(x_k,u_k,dt) + λ_k^T c_k(x_k,u_k) + c_k(x_k,u_k)^T I_{\mu_k} c_k(x_k,u_k)
\end{align*}
```

This function is then minimized with respect to the primal variables using any unconstrained minimization solver (e.g. iLQR).
    After a local minima is found, the AL method updates the Lagrange multipliers λ and the penalty terms μ and repeats the unconstrained minimization.
    AL methods have superlinear convergence as long as the penalty term μ is updated each iteration.
"""
struct AugmentedLagrangianSolver{T} <: AbstractSolver{T}
    opts::AugmentedLagrangianSolverOptions{T}
    stats::Dict{Symbol,Any}
    stats_uncon::Vector{Dict{Symbol,Any}}

    # Data variables
    C::PartedVecTrajectory{T}      # Constraint values [(p,N-1) (p_N)]
    C_prev::PartedVecTrajectory{T} # Previous constraint values [(p,N-1) (p_N)]
    ∇C::PartedMatTrajectory{T}   # Constraint jacobians [(p,n+m,N-1) (p_N,n)]
    λ::PartedVecTrajectory{T}      # Lagrange multipliers [(p,N-1) (p_N)]
    μ::PartedVecTrajectory{T}     # Penalty matrix [(p,p,N-1) (p_N,p_N)]
    active_set::PartedVecTrajectory{Bool} # active set [(p,N-1) (p_N)]

    solver_uncon::AbstractSolver
end

AugmentedLagrangianSolver(prob::Problem{T},
    opts::AugmentedLagrangianSolverOptions{T}=AugmentedLagrangianSolverOptions{T}()) where T =
    AbstractSolver(prob,opts)

"""$(TYPEDSIGNATURES)
Form an augmented Lagrangian cost function from a Problem and AugmentedLagrangianSolver.
    Does not allocate new memory for the internal arrays, but points to the arrays in the solver.
"""
function AbstractSolver(prob::Problem{T,D}, opts::AugmentedLagrangianSolverOptions{T}) where {T<:AbstractFloat,D<:DynamicsType}
    # check for conflicting convergence criteria between unconstrained solver and AL: warn

    # Init solver statistics
    to = TimerOutput()
    reset_timer!(to)
    stats = Dict{Symbol,Any}(:iterations=>0,:iterations_total=>0,
        :iterations_inner=>Int[],:cost=>T[],:c_max=>T[],:penalty_max=>[],
        :timer=>to)
    stats_uncon = Dict{Symbol,Any}[]

    # Init solver results
    n = prob.model.n; m = prob.model.m; N = prob.N

    C,∇C,λ,μ,active_set = init_constraint_trajectories(prob.constraints,n,m,N)

    solver_uncon = AbstractSolver(prob,opts.opts_uncon)
    solver_uncon.stats[:timer] = to

    AugmentedLagrangianSolver{T}(opts,stats,stats_uncon,C,copy(C),∇C,λ,μ,active_set,solver_uncon)
end

function init_constraint_trajectories(constraints::Constraints,n::Int,m::Int,N::Int;
        μ_init::T=1.,λ_init::T=0.) where T

    p = num_constraints(constraints)
    c_stage = [stage(constraints[k]) for k = 1:N-1]
    c_part = [create_partition(c_stage[k]) for k = 1:N-1]
    c_part2 = [create_partition2(c_stage[k],n,m) for k = 1:N-1]

    # Create Trajectories
    C          = [PartedVector(T,constraints[k],:stage)     for k = 1:N-1]
    ∇C         = [PartedMatrix(T,constraints[k],n,m,:stage) for k = 1:N-1]
    C          = [C...,  PartedVector(T,constraints[N],:terminal)]
    ∇C         = [∇C..., PartedMatrix(T,constraints[N],n,m,:terminal)]

    λ          = [PartedVector(ones(T,p[k]), C[k].parts)  for k = 1:N]
    μ          = [PartedVector(ones(T,p[k]), C[k].parts)  for k = 1:N]
    active_set = [PartedVector(ones(Bool,p[k]), C[k].parts)  for k = 1:N]

    # Initialize dual and penality values
    for k = 1:N
        λ[k] .*= λ_init
        μ[k] .*= μ_init
    end

    return C,∇C,λ,μ,active_set
end
AugmentedLagrangianSolver(prob::Problem, opts::AugmentedLagrangianSolverOptions) =
    AbstractSolver(prob, opts)

function reset!(solver::AugmentedLagrangianSolver{T}) where T
    solver.stats[:iterations]       = 0
    solver.stats[:iterations_total] = 0
    solver.stats[:iterations_inner] = T[]
    solver.stats[:cost]             = T[]
    solver.stats[:c_max]            = T[]
    solver.stats[:penalty_max]      = T[]
    solver.stats[:S_cond]           = T[]
    solver.stats[:Q_cond]           = T[]
    n,m,N = get_sizes(solver)
    for k = 1:N
        solver.λ[k] .*= 0
        solver.μ[k] .= solver.μ[k]*0 .+ solver.opts.penalty_initial
    end
end

function copy(r::AugmentedLagrangianSolver{T}) where T
    AugmentedLagrangianSolver{T}(deepcopy(r.C),deepcopy(r.C_prev),deepcopy(r.∇C),deepcopy(r.λ),deepcopy(r.μ),deepcopy(r.active_set))
end

get_sizes(solver::AugmentedLagrangianSolver{T}) where T = size(solver.∇C[1].x,2), size(solver.∇C[1].u,2), length(solver.λ)

max_issues_repo_name: MehrdadZareian/GMARA

max_forks_repo_name: MehrdadZareian/GMARA


text:
#Parses a string into a number if it can be represented as one
parse_if_num(s::AbstractString) = isa(parse(s), Number)  ? parse(s) : s

#Evaluates a function with the given args as strings
function eval_str(fn::AbstractString, args...)
  #Parse the arguments
  parsed_args = map(parse_if_num, [args...])

  #Evaluate the parsed expression
  eval(Expr(:call, parse(fn), parsed_args...))
end

function parse_args(args)#::Array{AbstractString, 1})
  dict = Dict{UTF8String, Any}(
    "max-tweets" => 10,
    "query" => "trump",
    "time" => 60,
    "db-handle" => "TwTXTFile.jl"
  )

  return dict
end

#=
Load 10 trump tweets into a file

julia stream_tweets.jl -dbh TwTXTFile -arg1 "path/to/txtfile.txt" -maxtweets 10 -q Trump

Possible arguments
-max-tweets (-m) <number>
  the maximum number of tweets to return
-query (-q) <string>
  the query
-time (-t) <number>
  the max number of seconds to search
  -time-<<unit>> (-t-<<unit>>) <number>
  the max number of <<unit>> to search
  will be converted to seconds before entering into dict
  example:
    -t-hour 4

-db-handle (-d) <string>
=#

max_stars_repo_name: nick-paul/JuliaTwitter

max_issues_repo_name: nick-paul/JuliaTwitter

max_forks_repo_name: nick-paul/JuliaTwitter


text:
module MixFit
    using Statistics
    include("special.jl")
    include("distributions.jl")
    include("mixutils.jl")
    include("em.jl")
end


text:
# The transformer below, not intended for the general user, wraps a
# single data-manipulating function without parameters, and is used by
# the @pipeline macro.  Generally, the only time the user will need to
# implement such a tranformer is when it also depends on parameters,
# and the recommendation is to instead subtype `Static` with a new
# custom type. In the context of a learning network, the user can use
# the `node` function to overload data-manipulating operations for
# nodes (if they are not already overloaded out-of-the-box).

const STATIC_TRANSFORMER_DESCR = "Applies a given data transformation
`f` (either a function or callable)."

"""
$STATIC_TRANSFORMER_DESCR

## Field

* `f=identity`: function or callable object to use for the data transformation.
"""
mutable struct StaticTransformer <: MLJBase.Unsupervised
    f
end
StaticTransformer(;f=identity) = StaticTransformer(f)

fitted_params(::StaticTransformer) = NamedTuple()
fit(::StaticTransformer, ::Integer, _) = nothing, nothing, NamedTuple()
transform(model::StaticTransformer, fitresult, Xnew) = (model.f)(Xnew)

MMI.metadata_model(StaticTransformer,
        input   = Table(Scientific),
        output  = Table(Scientific),
        weights = false,
        descr   = STATIC_TRANSFORMER_DESCR,
        path    = "MLJBase.StaticTransformer")

MMI.metadata_pkg(StaticTransformer,
        name    = "MLJBase",
        julia   = true,
        license = "MIT")


text:
# ==============================================================================
# Xavier Gandibleux - November 2021
#   Implemented in Julia 1.6

# ==============================================================================

println("""\nProject MOMH 2021" --------------------------------\n""")

const verbose = true
const graphic = true

include("parserMomkpZL.jl")
include("parserMomkpPG.jl")
include("vOptMomkp.jl")
include("displayGraphic.jl")

# ==============================================================================
# Datastructure of a generic bi-objective 0/1 IP where all coefficients are integer
#
#   Max  sum{j=1,...,n} C(k,j) x(j)                k=1,...,p
#   st   sum{j=1,...,n} A(i,j) x(j) <= b_{i}       i=1,...,m
#                       x(j) = 0 or 1

struct _bi01IP
    C  :: Matrix{Int} # objective functions, k=1..2, j=1..n
    A  :: Matrix{Int} # matrix of constraints, i=1..m, j=1..n
    b  :: Vector{Int} # right-hand side, i=1..m
end

# ==============================================================================

# Example ----------------------------------------------------------------------
fname = "instancesZL/knapsack.100.2"

# Read and load an instance of MO-01MKP from the collection of E. Zitzler / M. Laumanns
momkpZL = readInstanceMOMKPformatZL(verbose,fname)

# Reduce the MO-MKP instance to the two first objectives and store it as a generic Bi-01IP
dat1 = _bi01IP(momkpZL.P[1:2,:], momkpZL.W, momkpZL.ω)

# Example ----------------------------------------------------------------------
fname = "instancesPG/set1/ZL28.DAT"
#fname = "instancesPG/set2/kp28W-Perm.DAT"
#fname = "instancesPG/set3/W7BI-rnd1-1800.DAT"

# Read and load an instance of Bi-01BKP from the collection of O. Perederieieva / X. Gandibleux
momkpPG = readInstanceMOMKPformatPG(verbose,fname)

# Store it as a generic bi-01IP
dat2 = _bi01IP(momkpPG.P, momkpPG.W, momkpPG.ω)

# Example ----------------------------------------------------------------------
solverSelected = GLPK.Optimizer
#YN, XE = vSolveBi01IP(solverSelected, dat1.C, dat1.A, dat1.b)
YN, XE = vSolveBi01IP(solverSelected, dat2.C, dat2.A, dat2.b)

# ---- Displaying the results (XE and YN)
for n = 1:length(YN)
    X = value.(XE, n)
    print(findall(elt -> elt ≈ 1, X))
    println("| z = ",YN[n])
end

for n = 1:length(YN)
    println(YN[n])
end

# Example ----------------------------------------------------------------------
displayGraphics(fname,YN)

max_stars_repo_name: xgandibleux/momhMKPstu

max_issues_repo_name: xgandibleux/momhMKPstu

max_forks_repo_name: xgandibleux/momhMKPstu


text:
# Win32API

VERSION >= v"0.4.0-dev+6521" && __precompile__()
module Win32API

export MessageBoxA, MessageBoxW

function MessageBoxA(
  hwnd::Ptr{Void}, msg::AbstractString, title::AbstractString, opt::Int)
  return ccall((:MessageBoxA, :user32), stdcall,
    UInt, (Ptr{Void}, Ptr{UInt8}, Ptr{UInt8}, UInt),
    hwnd, msg, title, opt)
end

function MessageBoxW(
  hwnd::Ptr{Void}, msg::Array{Cwchar_t}, title::Array{Cwchar_t}, opt::Int)
  return ccall((:MessageBoxW, :user32), stdcall,
    UInt, (Ptr{Void}, Ptr{Cwchar_t}, Ptr{Cwchar_t}, UInt),
    hwnd, msg, title, opt)
end

end


text:
using DataDeps

register(DataDep(
  "triazines",
  "https://www.openml.org/d/206",
  "https://www.openml.org/data/get_csv/3643/dataset_2192_triazines.arff",
  "f6cf2b6604df302c869691b5e41cc2df010b051ac9f414d541f12958dd382ef1",
  post_fetch_method=(path -> begin
    UCIData.process_dataset(path,
        target_index=61,
        feature_indices=1:60,
        header=true,
    )
  end),
))

max_stars_repo_name: JackDunnNZ/uci-data

max_issues_repo_name: JackDunnNZ/uci-data

max_forks_repo_name: JackDunnNZ/uci-data


text:
module ProjectManagement
using DataStructures: MultiDict
using Compose
using Distributions
using Gadfly: Gadfly

using Graphs
using LayeredLayouts
using Random
using RecipesBase
using Statistics
using Random
export PertBeta, Project
export critical_path, density, sample_time, path_durations, visualize_chart

include("project.jl")
include("timing_distributions.jl")
include("timing_graphs.jl")
include("paths.jl")
include("graph_viz.jl")
end # module


text:
module EntityIds

using ..Ahorn, Maple

EntityTriggerType = Union{Maple.Entity, Maple.Trigger}

entityIdState = nothing
validIds = Ahorn.MultiRange()

# These types should be unsafe for getting new ids because of ridge gate/condition block
unsafeForReassign = Type[
    Strawberry,
    GoldenStrawberry,
    MemorialTextController,
    Key
]

function nextId()
    res, state = entityIdState === nothing ? iterate(validIds) : iterate(validIds, entityIdState)
    global entityIdState = state

    return res
end

function getUsedIds(map::Maple.Map)
    usedIds = Int[]

    for room in map.rooms
        append!(usedIds, Int.(getfield.(room.entities, :id)))
        append!(usedIds, Int.(getfield.(room.triggers, :id)))
    end

    return usedIds
end

function groupByIds(map::Maple.Map)
    res = Dict{Int, Array{EntityTriggerType, 1}}()

    for room in map.rooms
        for targets in [room.triggers, room.entities]
            for target in targets
                id = Int(target.id)

                get!(Array{EntityTriggerType, 1}, res, id)
                push!(res[id], target)
            end
        end
    end

    return res
end

function attemptIdFixing(map::Maple.Map, idGroupDict=groupByIds(map), force::Bool=false)
    success = true
    reassigned = 0

    for (id, targets) in idGroupDict
        if length(targets) > 1
            unsafeCount = 0

            for (i, target) in enumerate(targets)
                unsafeTargets = Bool[typeof(target) in unsafeForReassign for target in targets]
                unsafeCount = sum(unsafeTargets)

                if force
                    if i != 1
                        target.id = nextId()
                        reassigned += 1
                    end

                else
                    if unsafeCount > 0 && !unsafeTargets[i]
                        target.id = nextId()
                        reassigned += 1

                    elseif unsafeCount == 0 && i != 1
                        target.id = nextId()
                        reassigned += 1
                    end
                end
            end

            if unsafeCount > 1 && !force
                success = false
            end
        end
    end

    return success, reassigned
end

function getValidIdRanges(map::Maple.Map)
    usedIds = getUsedIds(map)
    sortedIds = sort(usedIds)

    gaps = UnitRange{Int}[]
    prev = -1

    for v in sortedIds
        if v !== prev && v - 1 !== prev
            push!(gaps, prev + 1:v - 1)
        end

        prev = v
    end

    push!(gaps, prev + 1:typemax(Int))

    return Ahorn.MultiRange(gaps)
end

function updateValidIds(map::Maple.Map)
    global validIds = getValidIdRanges(map)
    global entityIdState = nothing
end

end


text:
using PackageCompiler

target_dir = get(ENV, "OUTDIR", "$(@__DIR__)/../../MyLibCompiled")
target_dir = replace(target_dir, "\\"=>"/")       # Change Windows paths to use "/"

println("Creating library in $target_dir")
PackageCompiler.create_library(".", target_dir;
                                lib_name="mylib",
                                precompile_execution_file=["$(@__DIR__)/generate_precompile.jl"],
                                precompile_statements_file=["$(@__DIR__)/additional_precompile.jl"],
                                incremental=false,
                                filter_stdlibs=true,
                                header_files = ["$(@__DIR__)/mylib.h"],
                            )


text:
using MetaDataGraphs
using Documenter

DocMeta.setdocmeta!(MetaDataGraphs, :DocTestSetup, :(using MetaDataGraphs); recursive=true)

makedocs(;
    modules=[MetaDataGraphs],
    authors="Guillaume Dalle <22795598+gdalle@users.noreply.github.com> and contributors",
    repo="https://github.com/gdalle/MetaDataGraphs.jl/blob/{commit}{path}#{line}",
    sitename="MetaDataGraphs.jl",
    format=Documenter.HTML(;
        prettyurls=get(ENV, "CI", "false") == "true",
        canonical="https://gdalle.github.io/MetaDataGraphs.jl",
        assets=String[],
        edit_branch="main",
    ),
    pages=[
        "Home" => "index.md",
        "API reference" => [
            "AbstractDataGraph" => "api_abstract.md",
            "DataDiGraph" => "api_datadigraph.md",
        ],
    ],
)

deploydocs(;
    repo="github.com/gdalle/MetaDataGraphs.jl",
    devbranch="main",
)


text:
using BinaryBuilder, Pkg
using Base.BinaryPlatforms

const YGGDRASIL_DIR = "../.."
include(joinpath(YGGDRASIL_DIR, "fancy_toys.jl"))
include(joinpath(YGGDRASIL_DIR, "platforms", "llvm.jl"))

name = "Metal_LLVM_Tools"
repo = "https://github.com/JuliaGPU/llvm-metal"
version = v"0.2"

llvm_versions = [v"13.0.1"]

# Collection of sources required to build SPIRV_LLVM_Translator
sources = Dict(
    v"13.0.1" => [GitSource(repo, "aff6fc4f74785554643ae123a4df7c81074a6cbc")],
)

# These are the platforms we will build for by default, unless further
# platforms are passed in on the command line
platforms = [
    Platform("x86_64", "macos"; ),
    Platform("aarch64", "macos"; )
]
platforms = expand_cxxstring_abis(platforms)

# Bash recipe for building across all platforms
script = raw"""
cd llvm-metal/llvm
LLVM_SRCDIR=$(pwd)

install_license LICENSE.TXT

# The very first thing we need to do is to build llvm-tblgen for x86_64-linux-muslc
# This is because LLVM's cross-compile setup is kind of borked, so we just
# build the tools natively ourselves, directly.  :/

# Build llvm-tblgen and llvm-config
mkdir ${WORKSPACE}/bootstrap
pushd ${WORKSPACE}/bootstrap
CMAKE_FLAGS=()
CMAKE_FLAGS+=(-DLLVM_TARGETS_TO_BUILD:STRING=host)
CMAKE_FLAGS+=(-DLLVM_HOST_TRIPLE=${MACHTYPE})
CMAKE_FLAGS+=(-DCMAKE_BUILD_TYPE=Release)
CMAKE_FLAGS+=(-DLLVM_ENABLE_PROJECTS='llvm')
CMAKE_FLAGS+=(-DCMAKE_CROSSCOMPILING=False)
CMAKE_FLAGS+=(-DCMAKE_TOOLCHAIN_FILE=${CMAKE_HOST_TOOLCHAIN})
cmake -GNinja ${LLVM_SRCDIR} ${CMAKE_FLAGS[@]}
ninja -j${nproc} llvm-tblgen llvm-config
popd

# Let's do the actual build within the `build` subdirectory
mkdir ${WORKSPACE}/build && cd ${WORKSPACE}/build
CMAKE_FLAGS=()

# Tell LLVM where our pre-built tblgen tools are
CMAKE_FLAGS+=(-DLLVM_TABLEGEN=${WORKSPACE}/bootstrap/bin/llvm-tblgen)
CMAKE_FLAGS+=(-DLLVM_CONFIG_PATH=${WORKSPACE}/bootstrap/bin/llvm-config)

# Install things into $prefix
CMAKE_FLAGS+=(-DCMAKE_INSTALL_PREFIX=${prefix})

# Explicitly use our cmake toolchain file and tell CMake we're cross-compiling
CMAKE_FLAGS+=(-DCMAKE_TOOLCHAIN_FILE=${CMAKE_TARGET_TOOLCHAIN})
CMAKE_FLAGS+=(-DCMAKE_CROSSCOMPILING:BOOL=ON)

# Release build for best performance
CMAKE_FLAGS+=(-DCMAKE_BUILD_TYPE=Release)

# Only build the Metal back-end
CMAKE_FLAGS+=(-DLLVM_TARGETS_TO_BUILD=Metal)

cmake -GNinja ${LLVM_SRCDIR} ${CMAKE_FLAGS[@]}
ninja -j${nproc} \
    tools/metallib-as/install \
    tools/metallib-dis/install
"""

# The products that we will ensure are always built
products = Product[
    ExecutableProduct("metallib-as", :metallib_as),
    ExecutableProduct("metallib-dis", :metallib_dis),
]

augment_platform_block = """
    using Base.BinaryPlatforms

    $(LLVM.augment)

    function augment_platform!(platform::Platform)
        augment_llvm!(platform)
    end"""

# determine exactly which tarballs we should build
builds = []
for llvm_version in llvm_versions, llvm_assertions in (false, true)
    # Dependencies that must be installed before this package can be built
    llvm_name = llvm_assertions ? "LLVM_full_assert_jll" : "LLVM_full_jll"
    dependencies = [
        BuildDependency(PackageSpec(name=llvm_name, version=llvm_version))
    ]

    for platform in platforms
        augmented_platform = deepcopy(platform)
        augmented_platform[LLVM.platform_name] = LLVM.platform(llvm_version, llvm_assertions)

        should_build_platform(triplet(augmented_platform)) || continue
        push!(builds, (;
            dependencies,
            sources=sources[llvm_version],
            platforms=[augmented_platform],
        ))
    end
end

# don't allow `build_tarballs` to override platform selection based on ARGS.
# we handle that ourselves by calling `should_build_platform`
non_platform_ARGS = filter(arg -> startswith(arg, "--"), ARGS)

# `--register` should only be passed to the latest `build_tarballs` invocation
non_reg_ARGS = filter(arg -> arg != "--register", non_platform_ARGS)

for (i,build) in enumerate(builds)
    build_tarballs(i == lastindex(builds) ? non_platform_ARGS : non_reg_ARGS,
                   name, version, build.sources, script,
                   build.platforms, products, build.dependencies;
                   preferred_gcc_version=v"7", julia_compat="1.6",
                   augment_platform_block, lazy_artifacts=true)
end

max_stars_repo_name: staticfloat/BinaryBuilderRepos

max_issues_repo_name: staticfloat/BinaryBuilderRepos

max_forks_repo_name: staticfloat/BinaryBuilderRepos


text:
## Gather data back from RDA files
R"""
load(file = "generation_of_data_for_econ_analysis/waning_imm_scenario_1/kenya_inc_deaths_no_vac_w_vac.rda")
"""
kenya_inc_deaths_sc_1 = @rget kenya_inc_deaths
kenya_inc_deaths_sc_1 = sum(kenya_inc_deaths_sc_1, dims = 2)[:, 1, :]
kenya_inc_deaths = 0
R"""
kenya_inc_deaths = 0 #Free memory
"""
R"""
load(file = "generation_of_data_for_econ_analysis/waning_imm_scenario_2/kenya_inc_deaths_30_perc_w_vac.rda")
"""
kenya_inc_deaths_sc_2 = @rget kenya_inc_deaths
kenya_inc_deaths_sc_2 = sum(kenya_inc_deaths_sc_2, dims = 2)[:, 1, :]
kenya_inc_deaths = 0
R"""
kenya_inc_deaths = 0 #Free memory
"""
R"""
load(file = "generation_of_data_for_econ_analysis/waning_imm_scenario_3/kenya_inc_deaths_50_perc_w_vac.rda")
"""
kenya_inc_deaths_sc_3 = @rget kenya_inc_deaths
kenya_inc_deaths_sc_3 = sum(kenya_inc_deaths_sc_3, dims = 2)[:, 1, :]
kenya_inc_deaths = 0
R"""
kenya_inc_deaths = 0 #Free memory
"""
R"""
load(file = "generation_of_data_for_econ_analysis/waning_imm_scenario_4/kenya_inc_deaths_70_perc_w_vac.rda")
"""
kenya_inc_deaths_sc_4 = @rget kenya_inc_deaths
kenya_inc_deaths_sc_4 = sum(kenya_inc_deaths_sc_4, dims = 2)[:, 1, :]
kenya_inc_deaths = 0
R"""
kenya_inc_deaths = 0 #Free memory
"""
R"""
load(file = "generation_of_data_for_econ_analysis/waning_imm_scenario_5/kenya_inc_deaths_30_perc_rapid_w_vac.rda")
"""
kenya_inc_deaths_sc_5 = @rget kenya_inc_deaths
kenya_inc_deaths_sc_5 = sum(kenya_inc_deaths_sc_5, dims = 2)[:, 1, :]
kenya_inc_deaths = 0
R"""
kenya_inc_deaths = 0 #Free memory
"""
R"""
load(file = "generation_of_data_for_econ_analysis/waning_imm_scenario_6/kenya_inc_deaths_50_perc_rapid_w_vac.rda")
"""
kenya_inc_deaths_sc_6 = @rget kenya_inc_deaths
kenya_inc_deaths_sc_6 = sum(kenya_inc_deaths_sc_6, dims = 2)[:, 1, :]
kenya_inc_deaths = 0
R"""
kenya_inc_deaths = 0 #Free memory
"""
R"""
load(file = "generation_of_data_for_econ_analysis/waning_imm_scenario_7/kenya_inc_deaths_70_perc_rapid_w_vac.rda")
"""
kenya_inc_deaths_sc_7 = @rget kenya_inc_deaths
kenya_inc_deaths_sc_7 = sum(kenya_inc_deaths_sc_7, dims = 2)[:, 1, :]
kenya_inc_deaths = 0
R"""
kenya_inc_deaths = 0 #Free memory
"""