text:
using FractionalSystems, ControlSystems
using Test

@testset "Test FOTF" begin
    a = fotf([1, 2], [1, 2], [1, 2], [1, 2])

    @test isa(a, FOTF)
    @test fotfdata(a) == ([1, 2], [1, 2], [1, 2], [1, 2], 0)
    @test iszero(a) == false
    @test fotf("s") == fotf([1], [1], [1], [0], 0)
end

G = fotf([1, 2, 3], [0.1, 0.2, 0.34], [4, 5, 6], [0.65, 0.67, 0.78])
num = zeros(34+1)
num[34+1] = 3
num[20+1] = 2
num[10+1] = 1
num = num[end:-1:1]

den = zeros(78+1)
den[78+1] = 6
den[67+1] = 5
den[65+1] = 4
den = den[end:-1:1]

@testset "Test base_order" begin
    @test base_order(G) == 0.01
end

@testset "Test fotf2cotf" begin
    @test fotf2cotf(G) == tf(num, den)
end

@testset "Test Polyuniq" begin
    @test polyuniq([2, 2], [4, 4], 0.0001) == ([4], [4])
end
#=
@testset "Test simplify" begin
    g = fotf([2, 2], [4, 4], [6, 6], [8, 8])
    sg = fotf( 4, 0, 12, 4)
    @test fotfdata(simplify(g)) == fotfdata(sg)
end
=#

@testset "Test basic operations" begin
    a=fotf([5, 6], [7, 8], [1, 2], [3, 4])
    b=fotf([1, 2], [1, 2], [1, 2], [1, 2])

    aplusb = fotf([1, 5, 2, 6], [5, 4, 1, 0], [1, 2], [0, 1])
    @test a+b == aplusb
end

#=
@testset "Test inv operation" begin

end
=#

@testset "Test freqresp" begin
    a = fotf([1, 2], [1, 2], [1, 2], [1, 2])
    @test freqresp([1; 2; 3], a) == [1.0; 1.0; 1.0]
end

@testset "Test polyshow" begin
    @test polyshow([1, 2], [1, 2]) == "2s^{2}+s"
    @test polyshow([1, -2], [0, 2.2]) == "-2s^{2.2}+1"
end


text:
"""
```
    Equalization <: AbstractHistogramAdjustmentAlgorithm
    Equalization(; nbins = 256, minval = 0, maxval = 1)

    adjust_histogram([T,] img, f::Equalization)
    adjust_histogram!([out,] img, f::Equalization)
```

Returns a histogram equalized image with a granularity of `nbins` number of bins.

# Details

Histogram equalization was initially conceived to  improve the contrast in a
single-channel grayscale image. The method transforms the
distribution of the intensities in an image so that they are as uniform as
possible [1]. The natural justification for uniformity
is that the image has better contrast  if the intensity levels of an image span
a wide range on the intensity scale. As it turns out, the necessary
transformation is a mapping based on the cumulative histogram.

One can consider an ``L``-bit single-channel ``I \\times J`` image with gray
values in the set ``\\{0,1,\\ldots,L-1 \\}``, as a collection of independent and
identically distributed random variables. Specifically, let the sample space
``\\Omega`` be the set of all ``IJ``-tuples ``\\omega
=(\\omega_{11},\\omega_{12},\\ldots,\\omega_{1J},\\omega_{21},\\omega_{22},\\ldots,\\omega_{2J},\\omega_{I1},\\omega_{I2},\\ldots,\\omega_{IJ})``,
where each ``\\omega_{ij} \\in \\{0,1,\\ldots, L-1 \\}``. Furthermore, impose a
probability measure on ``\\Omega`` such that the functions ``\\Omega \\ni
\\omega \\to \\omega_{ij} \\in \\{0,1,\\ldots,L-1\\}`` are independent and
identically distributed.

One can then regard an image as a matrix of random variables ``\\mathbf{G} =
[G_{i,j}(\\omega)]``, where each function ``G_{i,j}: \\Omega \\to \\mathbb{R}``
is defined by
```math
G_{i,j}(\\omega) = \\frac{\\omega_{ij}}{L-1},
```
and each ``G_{i,j}`` is distributed according to some unknown density ``f_{G}``.
While ``f_{G}`` is unknown, one can approximate it with a normalized histogram
of gray levels,

```math
\\hat{f}_{G}(v)= \\frac{n_v}{IJ},
```
where
```math
n_v = \\left | \\left\\{(i,j)\\, |\\,  G_{i,j}(\\omega)  = v \\right \\} \\right |
```
represents the number of times a gray level with intensity ``v`` occurs in
``\\mathbf{G}``. To transform the distribution of the intensities so that
they are as uniform as possible one needs to find a mapping ``T(\\cdot)`` such
that ``T(G_{i,j}) \\thicksim U ``. The required mapping turns out to be the
cumulative distribution function (CDF) of the empirical density
``\\hat{f}_{G}``,
```math
 T(G_{i,j}) = \\int_0^{G_{i,j}}\\hat{f}_{G}(w)\\mathrm{d} w.
```

# Options

Various options for the parameters of the `adjust_histogram` function and
`Equalization` type are described in more detail below.

## Choices for `img`

The `adjust_histogram` function can handle a variety of
input types.  By default type of the returned image matches the input type.

For colored images, the input is converted to
[YIQ](https://en.wikipedia.org/wiki/YIQ) type and the Y channel is equalized.
This is the combined with the I and Q channels and the resulting image converted
to the same type as the input.

## Choices for `nbins` in `Equalization`

You can specify the total number of bins in the histogram.

## Choices for `minval` and `maxval` in `Equalization`

If `minval` and `maxval` are specified then intensities are equalized to the range
[`minval`, `maxval`]. The default values are 0 and 1.

# Example

```julia

using TestImages, FileIO, ImageView

img =  testimage("mandril_gray")
imgeq = adjust_histogram(img, Equalization(nbins = 256, minval = 0, maxval = 1))

imshow(img)
imshow(imgeq)
```

# References
1. R. C. Gonzalez and R. E. Woods. *Digital Image Processing (3rd Edition)*.  Upper Saddle River, NJ, USA: Prentice-Hall,  2006.
"""
@with_kw struct Equalization{T₁ <: Union{Real,AbstractGray},
                                T₂ <: Union{Real,AbstractGray}} <: AbstractHistogramAdjustmentAlgorithm
    nbins::Int = 256
    minval::T₁ = 0.0
    maxval::T₂ = 1.0
end

function (f::Equalization)(out::GenericGrayImage, img::GenericGrayImage)
    minval, maxval = convert(eltype(out), f.minval), convert(eltype(out), f.maxval)
    edges, histogram = build_histogram(img, f.nbins, minval = minval, maxval = maxval)
    lb = first(axes(histogram,1))
    ub = last(axes(histogram,1))
    N = length(img)
    cdf = cumsum(histogram[lb:ub]/N)
    newvals = build_lookup(cdf, minval, maxval)
    transform_density!(out, img, edges, newvals)
end

function (f::Equalization)(out::AbstractArray{<:Color3}, img::AbstractArray{<:Color3})
    T = eltype(img)
    yiq = convert.(YIQ, img)
    yiq_view = channelview(yiq)
    adjust_histogram!(view(yiq_view,1,:,:), f)
    out .= convert.(T, yiq)
end

(f::Equalization)(out::GenericGrayImage, img::AbstractArray{<:Color3}) =
    f(out, of_eltype(Gray, img))

ext: jl


text:
#=
function exchange1_1(solution,n,m,couts,crts,matrix)
    x_best = Solution(solution,calculz(solution,couts,n))
    # notre boucle k
    for i in 1:n
        if  x_best.x[i]  == 1
            x_prime = deepcopy(x_best)
            x_prime.x[i] = 0
            x_prime.objectif = calculz(x_prime.x,couts,n)
            # notre boucle p
            for j = 1:n
                if x_prime.x[j] == 0 && j != i # j != i car ça sers à rien de remettre une variable enlevée
                    x_seconde = deepcopy(x_prime)
                    x_seconde.x[j] = 1
                    x_seconde.objectif = calculz(x_prime.x,couts,n)
                    #on met à jour notre meilleur Solution
                    if x_seconde.objectif > x_best.objectif
                        x_best = deepcopy(x_seconde)
                    end
                end
            end
        end
    end
    #x,objectif= Solution.x
    return(x_best.x,x_best.objectif)
end
=#

#Reactive grasp final

#=
include("DM1_1.jl")
include("DM2_1.jl")
function ReactiveGRASP(matrix,cost, n, m, ite, coupe,temps)
#    println("^^^^^^^^ Debut R-GRASP ^^^^^^^^")
    #initialisation
    (p,nb_iteration,z_cumul,zBest,zWorst) = intialiser(matrix,cost, n, m, ite, coupe)
#    println("valeurs initiales: ")
#    println("p: ", p)
#    println("nb_iteration: ", nb_iteration)
#    println("z_cumul: ", z_cumul)
#    println("zBest: ", zBest , "  zWorst: ", zWorst)
    evol_p=Float64[]
    t=time()
    while (time()-t <= temps)
        cpt = 1
        append!(evol_p,p)
        while (cpt <= ite)
            for i in 1:length(p)
                (SOL,z) = GRASP(cost, matrix, n, m, p[i])
                z_cumul[i] += z
            end
            cpt = cpt+1
            prob=rand(Float64)
            alpha_choisit = choix_alpha(p,prob)
#            println("alpha_choisit: ", alpha_choisit, "  p: ", p)
            (SOL,z) = GRASP(cost, matrix, n, m, p[alpha_choisit])
            nb_iteration[alpha_choisit] += 1
            z_cumul[alpha_choisit] += z
            if z > zBest
                zBest = z
            end
            if z < zWorst
                zWorst = z
            end
#            println(" ============= \n ite: ",cpt)
        end
#        println("zBest: ", zBest, "   zWorst: ", zWorst)
#        println("  z_cumul: ",z_cumul)
#        println( "    nb_iteration : ", nb_iteration , "    p: ", p)
        recalcul_p!(p,z_cumul,zBest,zWorst,nb_iteration,evol_p)
        nb_iteration = ones(Int64, length(p))
        z_cumul = zeros(Int64, length(p))
    end
    println("^^^^^^^^ Fin ReactiveGRASP ^^^^^^^^")
    println("zBest: ", zBest, "    zWorst: ", zWorst)
    println(evol_p)
end
#=======================================#
function intialiser(matrix,cost, n, m, ite, coupe)
    p = Float64[]
    for i in 1:coupe
        push!(p,i/coupe)
    end
    nb_iteration = ones(Int64, length(p))
    z_cumul = zeros(Int64, length(p))
    (SOL,z) =Glouton(cost, matrix, n, m)
    zBest = z
    zWorst = z
    return(p,nb_iteration,z_cumul,zBest,zWorst)
end
#=======================================#
function recalcul_p!(p,z_cumul,zBest,zWorst,nb_iteration,evol_p)
    q=zeros(Float64,length(p))
    somme_q=0
#    println("q: ", q)
#    println("nb_iteration: ", nb_iteration)
    for i in 1:length(p)
#        println("q: ", q, "   i:", i)
#        if nb_iteration[i]!=0
#            println("z_cumul[i]: ", z_cumul[i],"   nb_iteration[i]: ", nb_iteration[i] )
            moyenne=(z_cumul[i]/nb_iteration[i])
#            println("moyenne: ", moyenne)
#        else
#            moyenne=0
#        end
#        if moyenne>0
            q[i]=(moyenne-zWorst)/(zBest-zWorst)
#            println("q[i]: ", q[i])
#        else
#            q[i]= zWorst/(zBest-zWorst)
#        end
        somme_q+=q[i]
    end
#    println("q: ", q, "      somme_q", somme_q)
    for i in 1:length(q)
        p[i]=q[i]/somme_q
    end
    for i in 2:length(p)-1
        p[i]+=p[i-1]
    end
    p[length(p)]=1
#    println("p: ", p)
end
#=======================================#
function choix_alpha(p,prob)
    for i in 1:length(p)
        if prob < p[i]
            return(i)
        elseif i==length(p)
            return(i)
        end
    end
end
=#
#=
#DM2_1
# =========================================================================== #
# =========================================================================== #
#Implementing an x0 viable solution huristic with a gluton method
#receiving an array of lenght()=m , a matrix of size m*n and thoose size
#returing a Bool array of lenght=n
#Asked question:
#Mettre en place une heuristique de construction d’une x0 réalisable.
function RandomGlouton(cost, matrix, n, m, alpha)
    #Creating a set of lines that will be avaluated
    actif= zeros(Bool, m) #if actif[j]=0 the line will be avaluated
    stop1= ones(Bool,m)
    #Creation the an array of activated variables
    varactive = ones(Bool, n)
    stop2= zeros(Bool , n)
#    println("\n varactive: ", varactive, "\n stop2: ", stop2)
    #creating my utility array for my m variables
    util = zeros(Float64, n)
    #initialisation de la Solution
    SOL = zeros(Float64, n)
#    println( "\n Matrix: ", matrix, "\n Cost: ", cost,"\n n= ", n, "   m= ", m,"\n actif: ", actif, "\n stop: ", stop1, "\n util: ", util, "\n SOL: ", SOL, "\n \n")
    ite = 0
    #Création de la solution
    while actif!=stop1 && varactive!=stop2
#      println("\n ++++++++++++++++++++++++++++++++++++++++")
#      println("\n itération: ", ite)
      #println("\n actif : ", actif, "\n stop1 : " , "\n varactive : " , varactive , "\n stop2 : ")
#      println("\n ++++++++++++++++++++++++++++++++++++++++")
        #Foction d'utilité
        util = Utilite(cost, matrix, actif, n, m , varactive, stop1, stop2)
        #Choix parmis les candidats de util
#        PosCandidat::Int64
#        PosCandidat = PosMax(util,n)
        PosCandidat::Int64 = choixcandidat(util, alpha)
        #On ajoute le candidat à la solution
        SOL[PosCandidat] = 1
        #Desactive! le candidat selectionné
        Desactive!(PosCandidat, matrix, actif, m, varactive,n)
        ite=ite+1
    end
    #println(calculz(SOL,cost,n))
    #return(SOL)
    Z = calculz(SOL,cost,n)
    println("Solution avant améliration: " , Z)
#    return(SOL, actif, Z)
    return(SOL, Z)
end
# =========================================================================== #
#Detremine an utility  based on an active (actif) set of matrix's lines
function Utilite(cost, matrix, actif, n, m , varactive, stop1, stop2)
#    println("==========================")
    util = zeros(Float64, n) #réinitialisation du vecteur
    #On each column of matrix
    for j=1:n
            if varactive[j] == 1
                    #For each line
                    for i=1:m
                        #checking if the line is active
                        if actif[i]==0 #&& i <= m
                            K=matrix[i,j]
                            util[j]=util[j]+K
#                            println("====== \n", "i: ", i ,"    j: ", j , "   k: ", K )
#                            println("\n varactive: ", varactive)
#                            println("\n actif : ", actif)
#                            println("\n util : ", util)
                        end
                    end
                # dividing the number if iterations of the variable j by its cost (not a zero)
                if util[j]!=false #On évide de divisé par 0...
#                    println("\n util avant modif: ", util)
                    util[j] =  cost[j] / util[j]
#                    println("\n util après modif: ", util)
                else
                    varactive[j] = 0
                end
            end
    end
#    println("\n Util: ", util)
#    println("\n \n ===================Utilite fini =============")
    return util
end
# =========================================================================== #
#=
function PosMax(util,n) #On choisie un candidat parmie les différents coûts, par ordre lexicographique
#println("%%%%%%%%%%%%%%%%%%%%")
#    Pos::Int64
    Pos=0
    ValCan=0.0
    for i=1:n
        if util[i] > ValCan
            ValCan = util[i]
            Pos = i
        end
    end
    #println("\n \n %%%%%% Pos max fini %%%%% \n pos: ", Pos)
    return Pos
end
=#
# =========================================================================== #
function Desactive!(PosCandidat, matrix, actif, m , varactive , n) #On désactive les lignes où est le candidat
#println("\n======================= desactive ==============================")
#println("~~~~~~~~~~~~~~~~~~~~~~~~")
    for i=1:m
#        println("\n Boucle i: ", i)
        if matrix[i,PosCandidat] == 1
#            println("\n If matrix[i,PosCandidat] == 1: " , matrix[i,PosCandidat])
            actif[i] = 1
#            println("\n actif[i] = 1: ", actif[i])
            for j=1:n
#                println("\n for j=1:n ; j: ", j)
                if matrix[i,j] ==1
#                    println("\n if matrix[i,j] ==1 :", matrix[i,j])
                    varactive[j] = 0
#                    println("\n varactive[j] = 0: ", varactive)
                end
            end
        end
    end
#    println("\n \n ~~~~~~~~~Desactive fini! ~~~~~~~\n ")
#    println("varactive: ", varactive)
#    println("actif: ", actif)
end
#=========================================================================#
function calculz(x,costs,m)
    z = 0
    for i in 1:m
        z+= x[i]*costs[i]
    end
    return z
end
#==========================================#
function choixcandidat(util, alpha)
    max = maximum(util)
    min = minimum(util)
#    Rut = Array{Float64}[]
    Rut = Float64[]
#    println("util: ", util, "\n type de util: ", typeof(util))
#    println("min: ", min, " max: ", max, " Rut: ", Rut)
    cpt::Int=1
    for i in 1:length(util)
#        println("debut for: ", i)
        if util[i]>= min+alpha*(max-min)
            push!(Rut,i)
        end
    end
    prob=rand(1:length(Rut))
#    println("fini, Rut: ", Rut, " Prob: ", prob)
    return(Rut[prob])
end
=#

#==
#Version 0
function choixcandidat(util, alpha)
    max = maximum(util)
    min = minimum(util)
#    Rut = Array{Float64}[]
    Rut = Float64[]
#    println("util: ", util, "\n type de util: ", typeof(util))
#    println("min: ", min, " max: ", max, " Rut: ", Rut)
    cpt::Int=1
    for i in 1:length(util)
#        println("debut for: ", i)
        if util[i]>= min+alpha*(max-min)
            push!(Rut,util[i])
        end
    end
    prob=rand(1:length(Rut))
#    println("fini, Rut: ", Rut, " Prob: ", prob)
    return(Rut[prob])
end
=#
#=
#Test run
z = Array{Float64}(undef, 42)
alpha = 0.9
println("z: ", z, " alpha : ", alpha)
cand=choixcandidat(z,alpha)
println("\n candidat choisit: ",cand)
==#
#=========================#
#=
DM1_1
# =========================================================================== #
# =========================================================================== #
#Implementing an x0 viable solution huristic with a gluton method
#receiving an array of lenght()=m , a matrix of size m*n and thoose size
#returing a Bool array of lenght=n
#Asked question:
#Mettre en place une heuristique de construction d’une x0 réalisable.
function Glouton(cost, matrix, n, m)
    #Creating a set of lines that will be avaluated
    actif= zeros(Bool, m) #if actif[j]=0 the line will be avaluated
    stop1= ones(Bool,m)
    #Creation the an array of activated variables
    varactive = ones(Bool, n)
    stop2= zeros(Bool , n)
#    println("\n varactive: ", varactive, "\n stop2: ", stop2)
    #creating my utility array for my m variables
    util = zeros(Float64, n)
    #initialisation de la Solution
    SOL = zeros(Float64, n)
#    println( "\n Matrix: ", matrix, "\n Cost: ", cost,"\n n= ", n, "   m= ", m,"\n actif: ", actif, "\n stop: ", stop1, "\n util: ", util, "\n SOL: ", SOL, "\n \n")
    ite = 0
    #Création de la solution
    while actif!=stop1 && varactive!=stop2
#      println("\n ++++++++++++++++++++++++++++++++++++++++")
#      println("\n itération: ", ite)
      #println("\n actif : ", actif, "\n stop1 : " , "\n varactive : " , varactive , "\n stop2 : ")
#      println("\n ++++++++++++++++++++++++++++++++++++++++")
        #Foction d'utilité
        util = Utilite(cost, matrix, actif, n, m , varactive, stop1, stop2)
        #Choix parmis les candidats de util
#        PosCandidat::Int64
        PosCandidat = PosMax(util,n)
        #On ajoute le candidat à la solution
        SOL[PosCandidat] = 1
        #Desactive! le candidat selectionné
        Desactive!(PosCandidat, matrix, actif, m, varactive,n)
        ite=ite+1
    end
    #println(calculz(SOL,cost,n))
    #return(SOL)
    Z = calculz(SOL,cost,n)
    println("Solution avant améliration: " , Z)
#    return(SOL, actif, Z)
    return(SOL, Z)
end
# =========================================================================== #
#Detremine an utility  based on an active (actif) set of matrix's lines
function Utilite(cost, matrix, actif, n, m , varactive, stop1, stop2)
#    println("==========================")
    util = zeros(Float64, n) #réinitialisation du vecteur
    #On each column of matrix
    for j=1:n
            if varactive[j] == 1
                    #For each line
                    for i=1:m
                        #checking if the line is active
                        if actif[i]==0 #&& i <= m
                            K=matrix[i,j]
                            util[j]=util[j]+K
#                            println("====== \n", "i: ", i ,"    j: ", j , "   k: ", K )
#                            println("\n varactive: ", varactive)
#                            println("\n actif : ", actif)
#                            println("\n util : ", util)
                        end
                    end
                # dividing the number if iterations of the variable j by its cost (not a zero)
                if util[j]!=false #On évide de divisé par 0...
#                    println("\n util avant modif: ", util)
                    util[j] =  cost[j] / util[j]
#                    println("\n util après modif: ", util)
                else
                    varactive[j] = 0
                end
            end
    end
#    println("\n Util: ", util)
#    println("\n \n ===================Utilite fini =============")
    return util
end
# =========================================================================== #
function PosMax(util,n) #On choisie un candidat parmie les différents coûts, par ordre lexicographique
#println("%%%%%%%%%%%%%%%%%%%%")
#    Pos::Int64
    Pos=0
    ValCan=0.0
    for i=1:n
        if util[i] > ValCan
            ValCan = util[i]
            Pos = i
        end
    end
    #println("\n \n %%%%%% Pos max fini %%%%% \n pos: ", Pos)
    return Pos
end
# =========================================================================== #
function Desactive!(PosCandidat, matrix, actif, m , varactive , n) #On désactive les lignes où est le candidat
#println("\n======================= desactive ==============================")
#println("~~~~~~~~~~~~~~~~~~~~~~~~")
    for i=1:m
#        println("\n Boucle i: ", i)
        if matrix[i,PosCandidat] == 1
#            println("\n If matrix[i,PosCandidat] == 1: " , matrix[i,PosCandidat])
            actif[i] = 1
#            println("\n actif[i] = 1: ", actif[i])
            for j=1:n
#                println("\n for j=1:n ; j: ", j)
                if matrix[i,j] ==1
#                    println("\n if matrix[i,j] ==1 :", matrix[i,j])
                    varactive[j] = 0
#                    println("\n varactive[j] = 0: ", varactive)
                end
            end
        end
    end
#    println("\n \n ~~~~~~~~~Desactive fini! ~~~~~~~\n ")
#    println("varactive: ", varactive)
#    println("actif: ", actif)
end
#=========================================================================#
function calculz(x,costs,m)
    z = 0
    for i in 1:m
        z+= x[i]*costs[i]
    end
    return z
end
=#

max_stars_repo_path: Archives/after the merge/brouillon.jl

max_issues_repo_path: Archives/after the merge/brouillon.jl

max_forks_repo_path: Archives/after the merge/brouillon.jl


text:
using BayesianDataFusion
using Base.Test

using DataFrames

A = randn(30,2);
B = randn(40,2);

X = Float64[ sum(A[i,:].*B[j,:]) for i in 1:size(A,1), j in 1:size(B,1) ]

df = DataFrame(A=Int64[], B=Int64[], v=Float64[])
for i=1:size(A,1), j=1:size(B,1)
  push!(df, Any[i, j, X[i,j]])
end

## adding features
feat = randn(size(df,1), 2)
beta = [1.0, -1.0]
df[:,end] = df[:,end] + feat * beta

rd = RelationData(df) #, alpha_sample = true)
rd.relations[1].model.alpha_sample = true
rd.relations[1].F = feat

assignToTest!(rd.relations[1], 10)
@test size(rd.relations[1].test_F) == (10,2)

result = macau(rd, burnin=50, psamples=10, num_latent=2, verbose=false)


text:
# Copyright (c) 2022 Code Komali
#
# This software is released under the MIT License.
# https://opensource.org/licenses/MIT

using Test

include("StudentData.jl")
using .StudentData

# Iterative version of merge
function merge(arr1::Vector, arr2::Vector, compareFn)
    iarr1 = 1
    iarr2 = 1
    res = []
    while iarr1 <= lastindex(arr1) && iarr2 <= lastindex(arr2)
        if compareFn(arr1[iarr1], arr2[iarr2])
            push!(res, arr1[iarr1])
            iarr1 += 1
        else
            push!(res, arr2[iarr2])
            iarr2 += 1
        end
    end
    if iarr1 <= lastindex(arr1)
        append!(res, arr1[iarr1:end])
    else
        append!(res, arr2[iarr2:end])
    end
end

@testset "Merge-iterative tests" begin
    @test merge([11, 6, 2], [9, 7, 5], (x, y) -> x > y) == [11,9,7,6,5,2]
    @test merge([2,6,11], [5,7,9], (x, y) -> x < y) == [2,5,6,7,9,11]
end

# Recursive implementation of merge
function merger(arr1::Vector, arr2::Vector, compareFn)
    if length(arr1) == 0
        arr2
    elseif length(arr2) == 0
        arr1
    elseif compareFn(arr1[1], arr2[1])
        [popfirst!(arr1); merger(arr1, arr2, compareFn)]
    else
        [popfirst!(arr2); merger(arr1, arr2, compareFn)]
    end
end

@testset "Merge-recursive tests" begin
    @test merger([11, 6, 2], [9, 7, 5], (x, y) -> x > y) == [11,9,7,6,5,2]
    @test merger([2,6,11], [5,7,9], (x, y) -> x < y) == [2,5,6,7,9,11]
end

# Recursive implementation of mergesort
function mergesortr(arr::Vector, desc = true,
    compareFn = desc ? (x,y)->x>y : (x,y) -> x<y)
    pivot = length(arr) ÷ 2
    if pivot == 0
        arr
    else
        merger(mergesortr(arr[1:pivot], desc, compareFn),
            mergesortr(arr[pivot+1:end], desc, compareFn),
            compareFn)
    end
end

# test for recursive mergesort
@testset "Mergesort-recursive tests" begin
    @test mergesortr([11, 9, 7, 10, 8, 6], true) == [11,10,9,8,7,6]
    @test mergesortr([11, 9, 7, 10, 8, 6], false) == [6,7,8,9,10,11]
    randArray = rand(Int8,10)
    @test mergesortr(randArray, true) == sort(randArray,rev=true) # Note: our mergesort implementation by default prefers descending order
    @test mergesortr(randArray, false) == sort(randArray)
    @test mergesortr(students,nothing,studentCompareFn) == sortedStudents
end

max_stars_repo_name: codekomali/JuliaPractice

max_issues_repo_name: codekomali/JuliaPractice

max_forks_repo_name: codekomali/JuliaPractice


text:
module adapters_postgresql_prepare_test

using Test # @test
using Octo.Adapters.PostgreSQL # Schema PREPARE EXECUTE

struct User
end
Schema.model(User, table_name="users")

struct Log
end
Schema.model(Log, table_name="logs")

u = from(User, :u)
l = from(Log, :l)
H = Octo.PlaceHolder

q = [PREPARE Raw("usrrptplan (int)") AS SELECT * FROM (u, l) WHERE u.usrid == H AND u.usrid == l.usrid AND l.date == H]
@test to_sql(q) == "PREPARE usrrptplan (int) AS SELECT * FROM users u, logs l WHERE u.usrid = \$1 AND u.usrid = l.usrid AND l.date = \$2"

@sql_functions usrrptplan
q = [EXECUTE usrrptplan(1, :current_date)]
@test to_sql(q) == "EXECUTE usrrptplan(1, current_date)"

end # module adapters_postgresql_prepare_test


text:
module ImageMorphology

using ImageCore
using ImageCore: GenericGrayImage
using OffsetArrays
using OffsetArrays: centered
using LinearAlgebra
using TiledIteration: EdgeIterator, SplitAxis, SplitAxes
using Requires
using LoopVectorization

const _docstring_se = """
`se` is the structuring element that defines the neighborhood of the image. See
[`strel`](@ref) for more details. If `se` is not specified, then it will use the
[`strel_box`](@ref) with an extra keyword `dims` to control the dimensions to filter,
and half-size `r` to control the diamond size.
"""
include("StructuringElements/StructuringElements.jl")
using .StructuringElements

include("convexhull.jl")
include("connected.jl")
include("clearborder.jl")
include("extreme_filter.jl")
include("ops/dilate.jl")
include("ops/erode.jl")
include("ops/closing.jl")
include("ops/opening.jl")
include("ops/tophat.jl")
include("ops/bothat.jl")
include("ops/mgradient.jl")
include("ops/mlaplacian.jl")
include("isboundary.jl")
include("thinning.jl")
include("imfill.jl")
include("maxtree.jl")

include("feature_transform.jl")
include("utils.jl")
using .FeatureTransform

include("deprecations.jl")

export
    # structuring_element.jl
    centered, # from OffsetArrays
    strel,
    strel_chain,
    strel_product,
    strel_type,
    strel_size,
    strel_diamond,
    strel_box,

    # operations
    dilate,
    dilate!,
    erode,
    erode!,
    extreme_filter,
    extreme_filter!,
    opening,
    opening!,
    closing,
    closing!,
    tophat,
    tophat!,
    bothat,
    bothat!,
    mgradient,
    mgradient!,
    mlaplacian,
    mlaplacian!,

    # connected.jl
    label_components,
    label_components!,
    component_boxes,
    component_lengths,
    component_indices,
    component_subscripts, # deprecated (v0.4)
    component_centroids,

    # convexhull.jl
    convexhull,

    # isboundary.jl
    isboundary,
    isboundary!,

    # thinning.jl
    thinning,
    GuoAlgo,
    imfill,

    # maxtree.jl
    MaxTree,
    areas,
    boundingboxes,
    diameters,
    area_opening,
    area_opening!,
    area_closing,
    area_closing!,
    diameter_opening,
    diameter_opening!,
    diameter_closing,
    diameter_closing!,
    local_maxima!,
    local_maxima,
    local_minima!,
    local_minima,

    #feature_transform.jl
    feature_transform,
    distance_transform,
    clearborder

function __init__()
    @require ImageMetadata = "bc367c6b-8a6b-528e-b4bd-a4b897500b49" begin
        # morphological operations for ImageMeta
        function dilate(img::ImageMetadata.ImageMeta; kwargs...)
            out = dilate!(similar(ImageMetadata.arraydata(img)), img; kwargs...)
            return ImageMetadata.shareproperties(img, out)
        end
        function erode(img::ImageMetadata.ImageMeta; kwargs...)
            out = erode!(similar(ImageMetadata.arraydata(img)), img; kwargs...)
            return ImageMetadata.shareproperties(img, out)
        end
    end
end

end # module


text:
import Playground.EquilateralIterators.getsortededges

@testset "EquilateralIterator" begin
    distmats = map(datasets) do (pts, metric, r)
        pts = pts[1:100]
        T = eltype(eltype(pts))
        n = length(eltype(pts))
        m = length(pts)
        pairwise(metric, reshape(reinterpret(T, pts), (n, m))), r
    end

    @testset "sortededges" begin
        for (dists, _) in distmats

            sortededges = getsortededges(dists)

            @test issorted([dists[e...] for e in sortededges])
            @test all(>(e...) for e in sortededges)
            @test length(sortededges) == binomial(size(dists, 1), 2)
        end
    end

    @testset "unique, sorted, equilateral" begin
        for (dists, r) in distmats
            Δlt(t1, t2) = isless(maximum(dists[i, j] for (i, j) in IterTools.subsets(t1, 2)),
                                 maximum(dists[i, j] for (i, j) in IterTools.subsets(t2, 2)))
            triangles = collect(equilaterals(dists, r))

            @test allunique(triangles)
            # triangles by side length
            @test issorted(getindex.(triangles, 1), lt = Δlt)
            # triangles by r
            @test issorted(getindex.(triangles, 2))

            function isequilateral(t1)
                a, b, c = (dists[i, j] for (i, j) in IterTools.subsets(t1, 2))
                abs(a - b) ≤ r && abs(b - c) ≤ r && abs(a - c) ≤ r
            end

            @test all(isequilateral, getindex.(triangles, 1))
        end
    end

    @testset "counts" begin
        h = √3/2
        #   *
        #  * *
        # * * *
        pts = [0 1 2 0.5 1.5 1;
               0 0 0 h   h   2h]
        dists  = pairwise(Euclidean(), pts)
        Δs = collect(equilaterals(dists, 0.1))

        @test length(Δs) == 5

        #   * * *
        #  * * *
        # * * *
        h   = √3/2
        pts = [0 1 2 0.5 1.5 2.5 1  2  3;
               0 0 0 h   h   h   2h 2h 2h]
        dists  = pairwise(Euclidean(), pts)
        Δs = collect(equilaterals(dists, 0.1))

        @test length(Δs) == 12

        # All points the same distance apart -- all triangles are eqilateral.
        n = 100
        dists = ones(Int, n, n)
        for i in 1:n
            dists[i, i] = 0
        end
        Δs = collect(equilaterals(Symmetric(dists), 0.0))

        @test length(Δs) == binomial(n, 3)
    end
end


text:
export alnfillrandom, alnfillrandom!, aln2perm
# Given an alignment f from set V1 to V2, that does not
# map all points in V1, map the rest of the points randomly
alnfillrandom(f::AbstractVector{<:Integer}, n::Integer) = alnfillrandom!(copy(f),n)
function alnfillrandom!(f::AbstractVector{<:Integer}, n::Integer)
    zpts = find(iszero, f)
    nzpts = find(!iszero, f)
    remf = setdiff(1:n, f[nzpts])
    shuffle!(remf)
    f[zpts] = remf[1:length(zpts)]
    f
end

function aln2perm(f::AbstractVector{Int},n::Integer)
    m = length(f)
    p = zeros(Int, n)
    p[1:m] = f
    mapped_to = zeros(Int,n)
    for i = 1:n
        if p[i] > 0
            mapped_to[p[i]] = 1
        end
    end
    j = 1
    for i = 1:n
        if mapped_to[i] == 0
            mapped_to[j] = i
            j += 1
        end
    end
    rp = randperm(n-m)
    for i = 1:(n-m)
        p[m+i] = mapped_to[rp[i]]
    end
    p
end


text:
@testset "Basic Constraint Tests" begin
    mock   = MOIU.MockOptimizer(Model{Float64}())
    config = MOIT.TestConfig()
    MOIT.basic_constraint_tests(mock, config)
end

@testset "Unit Tests" begin
    mock = MOIU.MockOptimizer(Model{Float64}())
    config = MOIT.TestConfig()
    MOIT.unittest(mock, config, [
        "solve_blank_obj",
        "solve_constant_obj",
        "solve_singlevariable_obj",
        "solve_with_lowerbound",
        "solve_with_upperbound",
        "solve_affine_lessthan",
        "solve_affine_greaterthan",
        "solve_affine_equalto",
        "solve_affine_interval",
        "solve_duplicate_terms_scalar_affine",
        "solve_duplicate_terms_vector_affine",
        "solve_qp_edge_cases",
        "solve_qcp_edge_cases",
        "solve_affine_deletion_edge_cases",
        "solve_duplicate_terms_obj",
        "solve_integer_edge_cases",
        "solve_objbound_edge_cases"
        ])

    @testset "solve_blank_obj" begin
        MOIU.set_mock_optimize!(mock,
            (mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!(mock,
                MOI.OPTIMAL,
                (MOI.FEASIBLE_POINT, [1]),
                MOI.FEASIBLE_POINT
            )
        )
        MOIT.solve_blank_obj(mock, config)
        # The objective is blank so any primal value ≥ 1 is correct
        MOIU.set_mock_optimize!(mock,
            (mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!(mock,
                MOI.OPTIMAL,
                (MOI.FEASIBLE_POINT, [2]),
                MOI.FEASIBLE_POINT
            )
        )
        MOIT.solve_blank_obj(mock, config)
    end
    @testset "solve_constant_obj" begin
        MOIU.set_mock_optimize!(mock,
            (mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!(mock,
                MOI.OPTIMAL,
                (MOI.FEASIBLE_POINT, [1]),
                MOI.FEASIBLE_POINT
            )
        )
        MOIT.solve_constant_obj(mock, config)
    end
    @testset "solve_singlevariable_obj" begin
        MOIU.set_mock_optimize!(mock,
            (mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!(mock,
                MOI.OPTIMAL,
                (MOI.FEASIBLE_POINT, [1]),
                MOI.FEASIBLE_POINT
            )
        )
        MOIT.solve_singlevariable_obj(mock, config)
    end
    @testset "solve_with_lowerbound" begin
        MOIU.set_mock_optimize!(mock,
            (mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!(mock,
                MOI.OPTIMAL,
                (MOI.FEASIBLE_POINT, [1]),
                MOI.FEASIBLE_POINT,
                    (MOI.SingleVariable, MOI.GreaterThan{Float64}) => [2.0],
                    (MOI.SingleVariable, MOI.LessThan{Float64})    => [0.0]
            )
        )
        # x has two variable constraints
        mock.eval_variable_constraint_dual = false
        MOIT.solve_with_lowerbound(mock, config)
        mock.eval_variable_constraint_dual = true
    end
    @testset "solve_with_upperbound" begin
        MOIU.set_mock_optimize!(mock,
            (mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!(mock,
                MOI.OPTIMAL,
                (MOI.FEASIBLE_POINT, [1]),
                MOI.FEASIBLE_POINT,
                    (MOI.SingleVariable, MOI.LessThan{Float64})    => [-2.0],
                    (MOI.SingleVariable, MOI.GreaterThan{Float64}) => [0.0]
            )
        )
        # x has two variable constraints
        mock.eval_variable_constraint_dual = false
        MOIT.solve_with_upperbound(mock, config)
        mock.eval_variable_constraint_dual = true
    end
    @testset "solve_affine_lessthan" begin
        MOIU.set_mock_optimize!(mock,
            (mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!(mock,
                MOI.OPTIMAL,
                (MOI.FEASIBLE_POINT, [0.5]),
                MOI.FEASIBLE_POINT,
                    (MOI.ScalarAffineFunction{Float64}, MOI.LessThan{Float64}) => [-0.5]
            )
        )
        MOIT.solve_affine_lessthan(mock, config)
    end
    @testset "solve_affine_greaterthan" begin
        MOIU.set_mock_optimize!(mock,
            (mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!(mock,
                MOI.OPTIMAL,
                (MOI.FEASIBLE_POINT, [0.5]),
                MOI.FEASIBLE_POINT,
                    (MOI.ScalarAffineFunction{Float64}, MOI.GreaterThan{Float64}) => [0.5]
            )
        )
        MOIT.solve_affine_greaterthan(mock, config)
    end
    @testset "solve_affine_equalto" begin
        MOIU.set_mock_optimize!(mock,
            (mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!(mock,
                MOI.OPTIMAL,
                (MOI.FEASIBLE_POINT, [0.5]),
                MOI.FEASIBLE_POINT,
                    (MOI.ScalarAffineFunction{Float64}, MOI.EqualTo{Float64}) => [0.5]
            )
        )
        MOIT.solve_affine_equalto(mock, config)
    end
    @testset "solve_affine_interval" begin
        MOIU.set_mock_optimize!(mock,
            (mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!(mock,
                MOI.OPTIMAL,
                (MOI.FEASIBLE_POINT, [2.0]),
                MOI.FEASIBLE_POINT,
                    (MOI.ScalarAffineFunction{Float64}, MOI.Interval{Float64}) => [-1.5]
            )
        )
        MOIT.solve_affine_interval(mock, config)
    end
    @testset "solve_duplicate_terms_scalar_affine" begin
        MOIU.set_mock_optimize!(mock,
            (mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!(mock,
                MOI.OPTIMAL,
                (MOI.FEASIBLE_POINT, [0.5]),
                MOI.FEASIBLE_POINT,
                    (MOI.ScalarAffineFunction{Float64}, MOI.LessThan{Float64}) => [-0.5]
            )
        )
        MOIT.solve_duplicate_terms_scalar_affine(mock, config)
    end
    @testset "solve_duplicate_terms_vector_affine" begin
        MOIU.set_mock_optimize!(mock,
            (mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!(mock,
                MOI.OPTIMAL,
                (MOI.FEASIBLE_POINT, [0.5]),
                MOI.FEASIBLE_POINT,
                    (MOI.VectorAffineFunction{Float64}, MOI.Nonpositives) => [[-0.5]]
            )
        )
        MOIT.solve_duplicate_terms_vector_affine(mock, config)
    end

    @testset "solve_qcp_edge_cases" begin
        MOIU.set_mock_optimize!(mock,
            (mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!(mock,
                MOI.OPTIMAL,
                (MOI.FEASIBLE_POINT, [0.5, 0.5])
            ),
            (mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!(mock,
                MOI.OPTIMAL,
                (MOI.FEASIBLE_POINT, [0.5, (√13 - 1)/4])
            )
        )
        MOIT.solve_qcp_edge_cases(mock, config)
    end

    @testset "solve_qp_edge_cases" begin
        MOIU.set_mock_optimize!(mock,
            (mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!(mock,
                MOI.OPTIMAL,
                (MOI.FEASIBLE_POINT, [1.0, 2.0])
            ),
            (mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!(mock,
                MOI.OPTIMAL,
                (MOI.FEASIBLE_POINT, [1.0, 2.0])
            ),
            (mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!(mock,
                MOI.OPTIMAL,
                (MOI.FEASIBLE_POINT, [1.0, 2.0])
            ),
            (mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!(mock,
                MOI.OPTIMAL,
                (MOI.FEASIBLE_POINT, [1.0, 2.0])
            )
        )
        MOIT.solve_qp_edge_cases(mock, config)
    end
    @testset "solve_duplicate_terms_obj" begin
        MOIU.set_mock_optimize!(mock,
            (mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!(mock,
                MOI.OPTIMAL,
                (MOI.FEASIBLE_POINT, [1]),
                MOI.FEASIBLE_POINT
            )
        )
        MOIT.solve_duplicate_terms_obj(mock, config)
    end
    @testset "solve_affine_deletion_edge_cases" begin
        MOIU.set_mock_optimize!(mock,
            (mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!(mock,
                MOI.OPTIMAL, (MOI.FEASIBLE_POINT, [0.0])
            ),
            (mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!(mock,
                MOI.OPTIMAL, (MOI.FEASIBLE_POINT, [0.0])
            ),
            (mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!(mock,
                MOI.OPTIMAL, (MOI.FEASIBLE_POINT, [1.0])
            ),
            (mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!(mock,
                MOI.OPTIMAL, (MOI.FEASIBLE_POINT, [1.0])
            ),
            (mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!(mock,
                MOI.OPTIMAL, (MOI.FEASIBLE_POINT, [2.0])
            )
        )
        MOIT.solve_affine_deletion_edge_cases(mock, config)
    end
    @testset "solve_integer_edge_cases" begin
        MOIU.set_mock_optimize!(mock,
            (mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!(mock,
                MOI.OPTIMAL, (MOI.FEASIBLE_POINT, [2.0])
            ),
            (mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!(mock,
                MOI.OPTIMAL, (MOI.FEASIBLE_POINT, [1.0])
            ),
            (mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!(mock,
                MOI.OPTIMAL, (MOI.FEASIBLE_POINT, [1.0])
            ),
            (mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!(mock,
                MOI.OPTIMAL, (MOI.FEASIBLE_POINT, [0.0])
            )
        )
        MOIT.solve_integer_edge_cases(mock, config)
    end
    @testset "solve_objbound_edge_cases" begin
        MOIU.set_mock_optimize!(mock,
            (mock::MOIU.MockOptimizer) -> begin
                MOI.set(mock, MOI.ObjectiveBound(), 3.0)
                MOIU.mock_optimize!(mock, MOI.OPTIMAL, (MOI.FEASIBLE_POINT, [2.0]))
            end,
            (mock::MOIU.MockOptimizer) -> begin
                MOI.set(mock, MOI.ObjectiveBound(), 3.0)
                MOIU.mock_optimize!(mock, MOI.OPTIMAL, (MOI.FEASIBLE_POINT, [1.0]))
            end,
            (mock::MOIU.MockOptimizer) -> begin
                MOI.set(mock, MOI.ObjectiveBound(), 2.0)
                MOIU.mock_optimize!(mock, MOI.OPTIMAL, (MOI.FEASIBLE_POINT, [1.5]))
            end,
            (mock::MOIU.MockOptimizer) -> begin
                MOI.set(mock, MOI.ObjectiveBound(), 4.0)
                MOIU.mock_optimize!(mock, MOI.OPTIMAL, (MOI.FEASIBLE_POINT, [1.5]))
            end
        )
        MOIT.solve_objbound_edge_cases(mock, config)
    end

end

@testset "modifications" begin
    mock   = MOIU.MockOptimizer(Model{Float64}())
    config = MOIT.TestConfig()
    @testset "solve_set_singlevariable_lessthan" begin
        MOIU.set_mock_optimize!(mock,
            (mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!(mock,
                MOI.OPTIMAL, (MOI.FEASIBLE_POINT, [1.0]),
                MOI.FEASIBLE_POINT
            ),
            (mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!(mock,
                MOI.OPTIMAL, (MOI.FEASIBLE_POINT, [2.0]),
                MOI.FEASIBLE_POINT
            )
        )
        MOIT.solve_set_singlevariable_lessthan(mock, config)
    end
    @testset "solve_transform_singlevariable_lessthan" begin
        MOIU.set_mock_optimize!(mock,
            (mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!(mock,
                MOI.OPTIMAL, (MOI.FEASIBLE_POINT, [1.0]),
                MOI.FEASIBLE_POINT
            ),
            (mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!(mock,
                MOI.OPTIMAL, (MOI.FEASIBLE_POINT, [2.0]),
                MOI.FEASIBLE_POINT
            )
        )
        MOIT.solve_transform_singlevariable_lessthan(mock, config)
    end
    @testset "solve_set_scalaraffine_lessthan" begin
        MOIU.set_mock_optimize!(mock,
            (mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!(mock,
                MOI.OPTIMAL, (MOI.FEASIBLE_POINT, [1.0]),
                MOI.FEASIBLE_POINT,
                    (MOI.ScalarAffineFunction{Float64}, MOI.LessThan{Float64}) => [-1.0]
            ),
            (mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!(mock,
                MOI.OPTIMAL, (MOI.FEASIBLE_POINT, [2.0]),
                MOI.FEASIBLE_POINT,
                    (MOI.ScalarAffineFunction{Float64}, MOI.LessThan{Float64}) => [-1.0]
            )
        )
        MOIT.solve_set_scalaraffine_lessthan(mock, config)
    end
    @testset "solve_coef_scalaraffine_lessthan" begin
        MOIU.set_mock_optimize!(mock,
            (mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!(mock,
                MOI.OPTIMAL, (MOI.FEASIBLE_POINT, [1.0]),
                MOI.FEASIBLE_POINT,
                    (MOI.ScalarAffineFunction{Float64}, MOI.LessThan{Float64}) => [-1.0]
            ),
            (mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!(mock,
                MOI.OPTIMAL, (MOI.FEASIBLE_POINT, [0.5]),
                MOI.FEASIBLE_POINT,
                    (MOI.ScalarAffineFunction{Float64}, MOI.LessThan{Float64}) => [-0.5]
            )
        )
        MOIT.solve_coef_scalaraffine_lessthan(mock, config)
    end
    @testset "solve_func_scalaraffine_lessthan" begin
        MOIU.set_mock_optimize!(mock,
            (mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!(mock,
                MOI.OPTIMAL, (MOI.FEASIBLE_POINT, [1.0]),
                MOI.FEASIBLE_POINT,
                    (MOI.ScalarAffineFunction{Float64}, MOI.LessThan{Float64}) => [-1.0]
            ),
            (mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!(mock,
                MOI.OPTIMAL, (MOI.FEASIBLE_POINT, [0.5]),
                MOI.FEASIBLE_POINT,
                    (MOI.ScalarAffineFunction{Float64}, MOI.LessThan{Float64}) => [-0.5]
            )
        )
        MOIT.solve_func_scalaraffine_lessthan(mock, config)
    end
    @testset "solve_const_vectoraffine_nonpos" begin
        MOIU.set_mock_optimize!(mock,
            (mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!(mock,
                MOI.OPTIMAL, (MOI.FEASIBLE_POINT, [0.0, 0.0])
            ),
            (mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!(mock,
                MOI.OPTIMAL, (MOI.FEASIBLE_POINT, [1.0, 0.75])
            )
        )
        MOIT.solve_const_vectoraffine_nonpos(mock, config)
    end
    @testset "solve_multirow_vectoraffine_nonpos" begin
        MOIU.set_mock_optimize!(mock,
            (mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!(mock,
                MOI.OPTIMAL, (MOI.FEASIBLE_POINT, [0.5])
            ),
            (mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!(mock,
                MOI.OPTIMAL, (MOI.FEASIBLE_POINT, [0.25])
            )
        )
        MOIT.solve_multirow_vectoraffine_nonpos(mock, config)
    end
    @testset "solve_const_scalar_objective" begin
        MOIU.set_mock_optimize!(mock,
            (mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!(mock,
                MOI.OPTIMAL, (MOI.FEASIBLE_POINT, [1.0])
            ),
            (mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!(mock,
                MOI.OPTIMAL, (MOI.FEASIBLE_POINT, [1.0])
            )
        )
        MOIT.solve_const_scalar_objective(mock, config)
    end
    @testset "solve_coef_scalar_objective" begin
        MOIU.set_mock_optimize!(mock,
            (mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!(mock,
                MOI.OPTIMAL, (MOI.FEASIBLE_POINT, [1.0])
            ),
            (mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!(mock,
                MOI.OPTIMAL, (MOI.FEASIBLE_POINT, [1.0])
            )
        )
        MOIT.solve_coef_scalar_objective(mock, config)
    end
    @testset "delete_variable_with_single_variable_obj" begin
        MOIU.set_mock_optimize!(mock,
            (mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!(mock,
                MOI.OPTIMAL, (MOI.FEASIBLE_POINT, [1.0]),
                MOI.FEASIBLE_POINT,
                (MOI.SingleVariable, MOI.GreaterThan{Float64}) => [1.0]
            )
        )
        MOIT.delete_variable_with_single_variable_obj(mock, config)
    end
end


text:
using Bridge, Distributions, StaticArrays
using Plots
using LinearAlgebra

#
t = 2.
n = 100
dt = t / n
x0 = 1.

# define a Float64 Wiener process
P = Wiener() #returns object representing standard Brownian motion

typeof(P)
#prints Bridge.Wiener{Float64}

supertype(typeof(P))
#prints Bridge.ContinuousTimeProcess{Float64}

# sample Brownian motion on an equidistant grid
W = sample(range(0., stop=t, length=n), P)
W = sample(0:dt:t, P) # similar way

println(W.tt)
# prints [0.0,0.03,0.06,..., 0.93.96,0.99]
plot(W.tt, W.yy)
# plots path

plot(W)
# Bridge defines a plot @recipe (via RecipesBase)

# sample complex Brownian motion on a nonequidistant grid

X = sample(sort(rand(1000)), Wiener{Complex{Float64}}())
plot(real(X.yy), imag(X.yy))

# sample a standard Brownian bridge ending in v at time s
s = 1.
v = 0.

B = sample(0:dt:s, WienerBridge(s, v))
plot(W.tt, W.yy, color="blue")
plot!(B.tt, B.yy, color="red")
# displays X and  Brownian bridge B in red

# Define a diffusion process
struct OrnsteinUhlenbeck  <: ContinuousTimeProcess{Float64}
    β::Float64 # drift parameter (also known as inverse relaxation time)
    σ::Float64 # diffusion parameter
    function OrnsteinUhlenbeck(β::Float64, σ::Float64)
        isnan(β) || β > 0. || error("Parameter λ must be positive.")
        isnan(σ) || σ > 0. || error("Parameter σ must be positive.")
        new(β, σ)
    end
end

# define drift and sigma of OrnsteinUhlenbeck
import Bridge: b, σ, a, transitionprob
Bridge.b(t,x, P::OrnsteinUhlenbeck) = -P.β*x
Bridge.σ(t, x, P::OrnsteinUhlenbeck) = P.σ
Bridge.a(t, x, P::OrnsteinUhlenbeck) = P.σ^2

# simulate OrnsteinUhlenbeck using Euler scheme
W = sample(0:0.01:10, Wiener{Float64}())
X = solve(EulerMaruyama(), 0.1, W, OrnsteinUhlenbeck(20., 1.))

plot(X.tt, X.yy)

# define transition density
transitionprob(s, x, t, P::OrnsteinUhlenbeck) = Normal(x*exp(-P.β*(t-s)), sqrt((0.5P.σ^2/P.β) *(1-exp(-2*P.β*(t-s)))))

# plot likelihood of β
LL = [(β, llikelihood(X, OrnsteinUhlenbeck(β, 1.))) for β in 1.:30.]
for (β, ll) in LL
    println("β $β loglikelihood ", ll )
end
plot(Float64[β for (β, ll) in LL], Float64[ll for (β, ll) in LL])

# sample OrnsteinUhlenbeck exactly. compare with euler scheme which degrates as dt = 0.07
X = solve(EulerMaruyama(), 0.1, sample(0:0.07:10, Wiener{Float64}()), OrnsteinUhlenbeck(20., 1.))
X2 = sample(0:0.07:10, OrnsteinUhlenbeck(20., 1.), 0.1)
plot(X.tt, 1 .+ X.yy)
plot!(X2.tt, X2.yy)

# sample vector Brownian motion
W2 = sample(0:0.1:10, Wiener{SVector{4,Float64}}())
llikelihood(W2,Wiener{SVector{4,Float64}}())

P = BridgeProp(OrnsteinUhlenbeck(3., 1.), 0:0.01:1,  (0., 1.), 1.)
X = solve(EulerMaruyama(), 0.1, sample(0:0.01:1, Wiener{Float64}()),P)

P2 = PBridgeProp(OrnsteinUhlenbeck(3., 1.), 0., 0., 1., 2., 2., 0., 1., 0.3, 1.)
Y = solve(EulerMaruyama(), 0.1, sample(0:0.01:2, Wiener{Float64}()),P2)
p = plot(Y.tt, Y.yy, xlim=(0, 2), ylim=(-3,3), legend=false)

for i in 1:100
    global Y = solve(EulerMaruyama(), 0.1, sample(0:0.01:2, Wiener{Float64}()),P2)
    plot!(p, Y.tt, Y.yy, xlim=(0, 2), ylim=(-3,3), linewidth=0.2)
end
display(p)

# Define a diffusion process
struct VOrnsteinUhlenbeck{d}  <: ContinuousTimeProcess{SVector{d,Float64}}
    β # drift parameter (also known as inverse relaxation time)
    σ # diffusion parameter
    function VOrnsteinUhlenbeck{d}(β, σ) where d
           new(β, σ)
    end
end

# define drift and sigma of VOrnsteinUhlenbeck

Bridge.b(t, x, P::VOrnsteinUhlenbeck) = -P.β*x
Bridge.σ(t, x, P::VOrnsteinUhlenbeck) = P.σ*I
Bridge.a(t, x, P::VOrnsteinUhlenbeck) = P.σ*P.σ'*I

# Simulate
tt = 0.:0.003:10.
X = solve(EulerMaruyama(), SVector(0., 0.), sample(tt, Wiener{SVector{2,Float64}}()), VOrnsteinUhlenbeck{2}(3., 1.))

yy = Bridge.mat(X.yy)
plot(yy[1,:], yy[2,:], xlim=(-2, 2), ylim=(-2,2), linewidth=0.5)


text:
export  SQLString,
        SQLColumn, Var

"""
```
SQLString( x )
```
This is a non-mutable struct that represents an SQL string constant. Any non-string entries are first processed to a string, then cast as a `SQLString` object.
"""
struct SQLString
    str::String

    SQLString( x::AbstractString ) = new(x)
end

SQLString( sqls::SQLString ) = sqls
SQLString( x ) = x |> processentry |> SQLString

Base.show( io::IO, sstr::SQLString ) = print( io, "'$(sstr.str)'" )

"""
```
SQLColumn(
    tablename::String,
    name::String )
SQLColumn( name::AbstractString )
```
This is a non-mutable struct that represents a column with a given `name` belonging to a specific table with name `tablename`, or the current table with the second calling method. It can also represent the name of an alias in the same manner.
"""
struct SQLColumn
    tablename::String
    name::String
end

SQLColumn( name::AbstractString ) = SQLColumn( "", name )

"""
`Var` is a shorthand for `SQLColumn`, the Julia type that represents a column or alias belonging to a specific database table (or the current one).
"""
const Var = SQLColumn
const SVar = Union{Var, AbstractString}
Var( sc::Var ) = sc

function Base.show( io::IO, sc::Var )
    isempty(sc.tablename) || print( io, "\"$(sc.tablename)\".")
    print( io, "\"$(sc.name)\"" )
end

Base.isempty( sc::Var ) = isempty(sc.name)

# Both functions are necessary for unique( scs::Vector{SQLColumn} ) to work.
Base.:(==)( sc1::Var, sc2::Var ) = sc1.name == sc2.name
Base.hash( sc::Var ) = hash("$(sc.tablename).$(sc.name)")

function makeunique!( v::Vector{SQLColumn} )
    vunique = unique(v)
    length(vunique) == length(v) && return v

    for el in vunique
        inds = findall(v .== Ref(el))

        for ii in 1:(length(inds) - 1)
            v[inds[ii+1]].name = string( v[inds[ii+1]].name, '_', ii )
        end
    end

    v
end


text:
"""Main module for Julia Optimization Heuristics"""
module JOH

export Solution, Problem

abstract type Solution end
abstract type ProblemID end
abstract type Problem end

include("Matheur/Matheur.jl")
include("Meta/Meta.jl")

end

max_stars_repo_name: Dibillilia/JuliaOptHeuristics

max_issues_repo_name: Dibillilia/JuliaOptHeuristics

max_forks_repo_name: Dibillilia/JuliaOptHeuristics


text:
struct OUUnknown{K} <: UnknownAcvTimeSeriesModel{1,Float64}
    σ::Float64
    θ::Float64
    σ²::Float64
    θ²::Float64
    function OUUnknown{K}(σ,θ) where {K}
        σ > 0 || throw(ArgumentError("OU process requires 0 < σ."))
        θ > 0 || throw(ArgumentError("OU process requires 0 < θ."))
        new(σ,θ,σ^2,θ^2)
    end
    function OUUnknown{K}(x::Vector{Float64}) where {K}
        @boundscheck checkparameterlength(x,OUUnknown{K})
        @inbounds OUUnknown{K}(x[1], x[2])
    end
end
nalias(::OUUnknown{K}) where {K} = K
npars(::Type{OUUnknown{K}}) where {K} = 2
lowerbounds(::Type{OUUnknown{K}}) where {K} = [0,0]
upperbounds(::Type{OUUnknown{K}}) where {K} = [Inf,Inf]

@inline sdf(m::OUUnknown, ω) = m.σ²/(π*(m.θ²+ω^2))

@propagate_inbounds function grad_add_sdf!(out, m::OUUnknown, ω)
    @boundscheck checkbounds(out,1:2)
    @inbounds begin
        σ, θ = m.σ, m.θ
        σ_part = 2σ / (π*(m.θ²+ω^2))
        out[1] += σ_part
        out[2] += -π*θ/2*(σ_part)^2
    end
    nothing
end

@propagate_inbounds function hess_add_sdf!(out, m::OUUnknown, ω)
    @boundscheck checkbounds(out,1:3)
    @inbounds begin
        σ, θ = m.σ, m.θ
        σ_part = 2 / (π*(m.θ²+ω^2))
        θσ_part = -π*θ*σ*(σ_part)^2
        out[1] += σ_part
        out[2] += θσ_part
        out[3] += -π*σ_part*σ*(σ_part*σ/2 + θ*θσ_part)
    end
    nothing
end


text:
### Based off of Ito.jl
struct NullCurrency <: AbstractCurrency end

struct Currency <: AbstractCurrency
	name::String
	code::String
	numeric::Int
	symbol::String
	fractionSymbol::String
	fractionsPerUnit::Int
	rounding::Function
	formatString::String
end

# Data from http://fx.sauder.ubc.ca/currency_table.html
# and http://www.thefinancials.com/vortex/CurrencyFormats.html

const list_currencies=[

# Africa
("South-African rand", "ZAR", 710, "R", "", 100, identity, "%3% %1\$.2f"),

# America
("Argentinian peso", "ARS", 32, "", "", 100, identity, "%2% %1\$.2f"),
("Brazilian real", "BRL", 986, "R\$", "", 100, identity, "%3% %1\$.2f"),
("Canadian dollar", "CAD", 124, "Can\$", "", 100, identity, "%3% %1\$.2f"),
("Chilean peso", "CLP", 152, "Ch\$", "", 100, identity, "%3% %1\$.0f"),
("Colombian peso", "COP", 170, "Col\$", "", 100, identity, "%3% %1\$.2f"),
("Mexican peso", "MXN", 484, "Mex\$", "", 100, identity, "%3% %1\$.2f"),
("Peruvian nuevo sol", "PEN", 604, "S/.", "", 100, identity, "%3% %1\$.2f"),
("Peruvian inti", "PEI", 998, "I/.", "", 100, identity, "%3% %1\$.2f"),
("Peruvian sol", "PEH", 999, "S./", "", 100, identity, "%3% %1\$.2f"),
("Trinidad & Tobago dollar", "TTD", 780, "TTD\$", "", 100, identity, "%3% %1\$.2f"),
("U.S. dollar", "USD", 840, "\$", "¢", 100, identity, "%3% %1\$.2f"),
("Venezuelan bolivar", "VEB", 862, "Bs", "", 100, identity, "%3% %1\$.2f"),

# Asia
("Bangladesh taka", "BDT", 50, "Bt", "", 100, identity, "%3% %1\$.2f"),
("Chinese yuan", "CNY", 156, "Y", "", 100, identity, "%3% %1\$.2f"),
("Hong Kong dollar", "HKD", 344, "HK\$", "", 100, identity, "%3% %1\$.2f"),
("Israeli shekel", "ILS", 376, "NIS", "", 100, identity, "%1\$.2f %3%"),
("Indian rupee", "INR", 356, "Rs", "", 100, identity, "%3% %1\$.2f"),
("Iraqi dinar", "IQD", 368, "ID", "", 1000, identity, "%2% %1\$.3f"),
("Iranian rial", "IRR", 364, "Rls", "", 1, identity, "%3% %1\$.2f"),
("Japanese yen", "JPY", 392, "¥", "", 100, identity, "%3% %1\$.0f"),
("South-Korean won", "KRW", 410, "W", "", 100, identity, "%3% %1\$.0f"),
("Kuwaiti dinar", "KWD", 414, "KD", "", 1000, identity, "%3% %1\$.3f"),
("Nepal rupee", "NPR", 524, "NRs", "", 100, identity, "%3% %1\$.2f"),
("Pakistani rupee", "PKR", 586, "Rs", "", 100, identity, "%3% %1\$.2f"),
("Saudi riyal", "SAR", 682, "SRls", "", 100, identity, "%3% %1\$.2f"),
("Singapore dollar", "SGD", 702, "S\$", "", 100, identity, "%3% %1\$.2f"),
("Thai baht", "THB", 764, "Bht", "", 100, identity, "%1\$.2f %3%"),
("Taiwan dollar", "TWD", 901, "NT\$", "", 100, identity, "%3% %1\$.2f"),

# Europe
("Bulgarian lev", "BGL", 100, "lv", "", 100, identity, "%1\$.2f %3%"),
("Belarussian ruble", "BYR", 974, "BR", "", 1, identity, "%2% %1\$.0f"),
("Swiss franc", "CHF", 756, "SwF", "", 100, identity, "%3% %1\$.2f"),
("Czech koruna", "CZK", 203, "Kc", "", 100, identity, "%1\$.2f %3%"),
("Danish krone", "DKK", 208, "Dkr", "", 100, identity, "%3% %1\$.2f"),
("European Euro", "EUR", 978, "", "", 100, x->round(x,2), "%2% %1\$.2f"),
("British pound sterling", "GBP", 826,  "£", "p", 100, identity, "%3% %1\$.2f"),
("Hungarian forint", "HUF", 348, "Ft", "", 1, identity, "%1\$.0f %3%"),
("Iceland krona", "ISK", 352, "IKr", "", 100, identity, "%1\$.2f %3%"),
("Lithuanian litas", "LTL", 440, "Lt", "", 100, identity, "%1\$.2f %3%"),
("Norwegian krone", "NOK", 578, "NKr", "", 100, identity, "%3% %1\$.2f"),
("Polish zloty", "PLN", 985, "zl", "", 100, identity, "%1\$.2f %3%"),
("Romanian leu", "ROL", 642, "L", "", 100, identity, "%1\$.2f %3%"),
("Romanian new leu", "RON", 946, "L", "", 100, identity, "%1\$.2f %3%"),
("Swedish krona", "SEK", 752, "kr", "", 100, identity, "%1\$.2f %3%"),
("Turkish lira", "TRL", 792, "TL", "", 100, identity, "%1\$.0f %3%"),
("New Turkish lira", "TRY", 949, "YTL", "", 100, identity, "%1\$.2f %3%"),

# Europe deprecated
("Austrian shilling", "ATS", 40, "", "", 100, identity, "%2% %1\$.2f"),
("Belgian franc", "BEF", 56, "", "", 1, identity, "%2% %1\$.0f"),
("Cyprus pound", "CYP", 196, "£", "", 100, identity, "%3% %1\$.2f"),
("Deutsche mark", "DEM", 276, "DM", "", 100, identity, "%1\$.2f %3%"),
("Estonian kroon", "EEK", 233, "KR", "", 100, identity, "%1\$.2f %2%"),
("Spanish peseta", "ESP", 724, "Pta", "", 100, identity, "%1\$.0f %3%"),
("Finnish markka", "FIM", 246, "mk", "", 100, identity, "%1\$.2f %3%"),
("French franc", "FRF", 250, "", "", 100, identity, "%1\$.2f %2%"),
("Greek drachma", "GRD", 300, "", "", 100, identity, "%1\$.2f %2%"),
("Irish punt", "IEP", 372, "", "", 100, identity, "%2% %1\$.2f"),
("Italian lira", "ITL", 380, "L", "", 1, identity, "%3% %1\$.0f"),
("Luxembourg franc", "LUF", 442, "F", "", 100, identity, "%1\$.0f %3%"),
("Latvian lat", "LVL", 428, "Ls", "", 100, identity, "%3% %1\$.2f"),
("Maltese lira", "MTL", 470, "Lm", "", 100, identity, "%3% %1\$.2f"),
("Dutch guilder", "NLG", 528, "f", "", 100, identity, "%3% %1\$.2f"),
("Portuguese escudo", "PTE", 620, "Esc", "", 100, identity, "%1\$.0f %3%"),
("Slovenian tolar", "SIT", 705, "SlT", "", 100, identity, "%1\$.2f %3%"),
("Slovak koruna", "SKK", 703, "Sk", "", 100, identity, "%1\$.2f %3%"),

# Oceania
("Australian dollar", "AUD", 36, "A\$", "", 100, identity, "%3% %1\$.2f"),
("New Zealand dollar", "NZD", 554, "NZ\$", "", 100, identity, "%3% %1\$.2f")
]

list_deprecated=Dict(
"ATS"=>"EUR",
"BEF"=>"EUR",
"CYP"=>"EUR",
"DEM"=>"EUR",
"EEK"=>"EUR",
"ESP"=>"EUR",
"FIM"=>"EUR",
"FRF"=>"EUR",
"GRD"=>"EUR",
"IEP"=>"EUR",
"ITL"=>"EUR",
"LUF"=>"EUR",
"LVL"=>"EUR",
"MTL"=>"EUR",
"NLG"=>"EUR",
"PTE"=>"EUR",
"SIT"=>"EUR",
"SKK"=>"EUR",
"TRL"=>"TRY",
"ROL"=>"RON",
"PEH"=>"PEI",
"PEI"=>"PEN"
)

# Codegen function
for currency in list_currencies
	@eval ($(Symbol("$(currency[2])"*"Currency")))()=Currency(($currency)...)
end


text:
# Note that this script can accept some limited command-line arguments, run
# `julia build_tarballs.jl --help` to see a usage message.
using BinaryBuilder

name = "Python"
version = v"3.8.1"

# Collection of sources required to build Python
sources = [
    ArchiveSource("https://www.python.org/ftp/python/$(version)/$(name)-$(version).tar.xz",
                  "75894117f6db7051c1b34f37410168844bbb357c139a8a10a352e9bf8be594e8"),
    DirectorySource("./bundled"),
]

# Bash recipe for building across all platforms
script = raw"""
# Having a global `python3` screws things up a bit, so get rid of that
rm -f $(which python3)

# We need these for the host python build
apk add zlib-dev libffi-dev

# Create fake `arch` command:
echo '#!/bin/bash' >> /usr/bin/arch
echo 'echo i386'   >> /usr/bin/arch
chmod +x /usr/bin/arch

# Patch out cross compile limitations
cd ${WORKSPACE}/srcdir/Python-*/
atomic_patch -p1 ${WORKSPACE}/srcdir/patches/cross_compile_configure_ac.patch
autoreconf -i

# Next, build host version
mkdir build_host && cd build_host

# Override `bb_target`, `CC`, etc... to give this `./configure` the impression
# that we are actually targeting `${MACHTYPE}` and not `${target}`
bb_target=${MACHTYPE} CC=${HOSTCC} CPPFLAGS=-I/usr/include LDFLAGS="-L/lib -L/usr/lib" ../configure --host="${MACHTYPE}" --build="${MACHTYPE}"
make -j${nproc} python sharedmods

# Next, build target version
cd ${WORKSPACE}/srcdir/Python-*/
mkdir build_target && cd build_target
export CPPFLAGS="${CPPFLAGS} -I${prefix}/include"
export LDFLAGS="${LDFLAGS} -L${prefix}/lib -L${prefix}/lib64"
export PATH=$(echo ${WORKSPACE}/srcdir/Python-*/build_host):$PATH
../configure --prefix="${prefix}" --host="${target}" --build="${MACHTYPE}" \
    --enable-shared \
    --disable-ipv6 \
    --with-ensurepip=no \
    ac_cv_file__dev_ptmx=no \
    ac_cv_file__dev_ptc=no \
    ac_cv_have_chflags=no
make -j${nproc}
make install
"""

# These are the platforms we will build for by default, unless further
# platforms are passed in on the command line
platforms = supported_platforms()

# Disable windows for now, until we can sort through all of these patches
# and choose the ones that we need:
# https://github.com/msys2/MINGW-packages/tree/1e753359d9b55a46d9868c3e4a31ad674bf43596/mingw-w64-python3
filter!(!Sys.iswindows, platforms)

# The products that we will ensure are always built
products = Product[
    ExecutableProduct(["python", "python3"], :python),
    LibraryProduct(["libpython3", "libpython3.8"], :libpython),
]

# Dependencies that must be installed before this package can be built
dependencies = [
    Dependency("Expat_jll", v"2.2.7"; compat="~2.2.7"),
    # Future versions of bzip2 should allow a more relaxed compat because the
    # soname of the macOS library shouldn't change at every patch release.
    Dependency("Bzip2_jll", v"1.0.6"; compat="=1.0.6"),
    Dependency("Libffi_jll", v"3.2.1"; compat="~3.2.1"),
    Dependency("Zlib_jll"),
    Dependency("XZ_jll"),
    Dependency("OpenSSL_jll"),
]

# Build the tarballs, and possibly a `build.jl` as well.
build_tarballs(ARGS, name, version, sources, script, platforms, products, dependencies)


text:
using Gadfly

plot(x=rand(10), y=rand(10), Guide.xticks(ticks=nothing), Guide.yticks(ticks=nothing))


text:
# This file is based on a part of Julia. License is MIT: https://julialang.org/license

# function tr(A::AbstractQuasiMatrix{T}) where T
#     n = checksquare(A)
#     t = zero(T)
#     for i=1:n
#         t += A[i,i]
#     end
#     t
# end

# function kron(a::AbstractMatrix{T}, b::AbstractMatrix{S}) where {T,S}
#     require_one_based_indexing(a, b)
#     R = Matrix{promote_op(*,T,S)}(undef, size(a,1)*size(b,1), size(a,2)*size(b,2))
#     m = 0
#     @inbounds for j = 1:size(a,2), l = 1:size(b,2), i = 1:size(a,1)
#         aij = a[i,j]
#         for k = 1:size(b,1)
#             R[m += 1] = aij*b[k,l]
#         end
#     end
#     R
# end

# kron(a::Number, b::Union{Number, AbstractVecOrMat}) = a * b
# kron(a::AbstractVecOrMat, b::Number) = a * b
# kron(a::AbstractVector, b::AbstractVector) = vec(kron(reshape(a ,length(a), 1), reshape(b, length(b), 1)))
# kron(a::AbstractMatrix, b::AbstractVector) = kron(a, reshape(b, length(b), 1))
# kron(a::AbstractVector, b::AbstractMatrix) = kron(reshape(a, length(a), 1), b)

# Matrix power
(^)(A::AbstractQuasiMatrix, p::Integer) =
    if p == 1
        copy(A)
    elseif p < 0
        inv(A)^(-p)
    else
        A*A^(p-1)
    end
function (^)(A::AbstractQuasiMatrix{T}, p::Integer) where T<:Integer
    # make sure that e.g. [1 1;1 0]^big(3)
    # gets promotes in a similar way as 2^big(3)
    TT = promote_op(^, T, typeof(p))
    return convert(AbstractQuasiMatrix{TT}, A)^p
end
# function integerpow(A::AbstractQuasiMatrix{T}, p) where T
#     TT = promote_op(^, T, typeof(p))
#     return (TT == T ? A : copyto!(similar(A, TT), A))^Integer(p)
# end

# function (^)(A::AbstractQuasiMatrix{T}, p::Real) where T
#     n = checksquare(A)

#     # Quicker return if A is diagonal
#     if isdiag(A)
#         TT = promote_op(^, T, typeof(p))
#         retmat = copy_oftype(A, TT)
#         for i in 1:n
#             retmat[i, i] = retmat[i, i] ^ p
#         end
#         return retmat
#     end

#     # For integer powers, use power_by_squaring
#     isinteger(p) && return integerpow(A, p)

#     # If possible, use diagonalization
#     if issymmetric(A)
#         return (Symmetric(A)^p)
#     end
#     if ishermitian(A)
#         return (Hermitian(A)^p)
#     end

#     # Otherwise, use Schur decomposition
#     return schurpow(A, p)
# end

# (^)(A::AbstractQuasiMatrix, p::Number) = exp(p*log(A))


text:
function Base.copy(x::Camera)
    Camera(ntuple(6) do i
        getfield(x, i)
    end...)
end
function Base.:(==)(a::Camera, b::Camera)
    value(a.view) == value(b.view) &&
    value(a.projection) == value(b.projection) &&
    value(a.resolution) == value(b.resolution)
end
function disconnect!(c::Camera)
    disconnect!(c.steering_nodes)
    return
end
function disconnect!(nodes::Vector)
    for node in nodes
        disconnect!(node)
    end
    empty!(nodes)
    return
end

"""
When mapping over nodes for the camera, we store them in the steering_node vector,
to make it easier to disconnect the camera steering signals later!
"""
function Base.map(f, c::Camera, nodes::Node...)
    node = map(f, nodes...)
    push!(c.steering_nodes, node)
    node
end

function Camera(px_area)
    Camera(
        Node(Mat4f0(I)),
        Node(Mat4f0(I)),
        Node(Mat4f0(I)),
        map(a-> Vec2f0(widths(a)), px_area),
        Node(Vec3f0(1)),
        Node[]
    )
end


text:
@defstruct SoftlabelSoftmaxLossLayer Layer (
  name :: AbstractString = "softlabel-softmax-loss",
  (weight :: AbstractFloat = 1.0, weight >= 0),
  (dim :: Int = -2, dim != 0),
  (bottoms :: Vector{Symbol} = Symbol[], length(bottoms) == 2),
)
@characterize_layer(SoftlabelSoftmaxLossLayer,
  has_loss => true,
  can_do_bp => true,
  is_sink => true
)

type SoftlabelSoftmaxLossLayerState{T} <: LayerState
  layer :: SoftlabelSoftmaxLossLayer
  loss  :: T

  softmax :: SoftmaxLayerState
  op_dim  :: Int
  etc     :: Any
end

function setup_etc(backend::CPUBackend, state::SoftlabelSoftmaxLossLayerState, inputs::Vector{Blob})
end
function setup(backend::Backend, layer::SoftlabelSoftmaxLossLayer, inputs::Vector{Blob}, diffs::Vector{Blob})
  data_type = eltype(inputs[1])
  tensor_dim = ndims(inputs[1])
  op_dim = layer.dim
  if op_dim < 0
    op_dim += tensor_dim + 1
  end
  @assert 1 <= op_dim <= tensor_dim
  @assert op_dim != tensor_dim # the last dimension is the mini-batch dimension

  softmax_layer = SoftmaxLayer(bottoms=[:softmax_input], tops=[:softmax_output], dim=layer.dim)
  softmax = setup(backend, softmax_layer, Blob[inputs[1]], Blob[diffs[1]])
  state = SoftlabelSoftmaxLossLayerState(layer, zero(data_type), softmax, op_dim, nothing)

  setup_etc(backend, state, inputs)

  return state
end

function shutdown_etc(backend::CPUBackend, state::SoftlabelSoftmaxLossLayerState)
end
function shutdown(backend::Backend, state::SoftlabelSoftmaxLossLayerState)
  shutdown_etc(backend, state)
  shutdown(backend, state.softmax)
end

function forward(backend::CPUBackend, state::SoftlabelSoftmaxLossLayerState, inputs::Vector{Blob})
  pred = inputs[1]
  label = inputs[2]

  forward(backend, state.softmax, Blob[pred])
  prob = state.softmax.blobs[1]

  dims = size(prob)
  state.loss = state.layer.weight * sum(-vec(log.(max.(prob.data, 1e-20))) .* vec(label.data)) / (prod(dims) / dims[state.op_dim])
end

function backward(backend::CPUBackend, state::SoftlabelSoftmaxLossLayerState, inputs::Vector{Blob}, diffs::Vector{Blob})
  diff = diffs[1]

  if isa(diff, CPUBlob)
    diff  = diff.data
    pred  = inputs[1].data
    label = inputs[2].data

    data_type = eltype(pred)
    copy!(diff, state.softmax.blobs[1])
    BLAS.axpy!(length(pred), -one(data_type), label, 1, diff, 1)
    dims = size(pred)
    Vec.mul_scal!(diff, state.layer.weight * dims[state.op_dim]/prod(dims))
  end
end


text:
"""
Finding and classifying h-motifs. Based on code from https://github.com/geonlee0325/MoCHy.
"""

include("Hypergraph.jl") # Used for working with hypergraphs
using SparseArrays # Used to construct the motif co-occurrence matrix

const motif_id = [ # Used for converting from three-way Venn to motif id
	0, 0, 0, 0, 0, 0, 17, 7,
	0, 0, 17, 7, 17, 7, 23, 13,
	0, 0, 0, 3, 0, 3, 18, 8,
	0, 0, 19, 9, 19, 9, 24, 14,
	0, 0, 0, 0, 0, 3, 19, 9,
	0, 3, 19, 9, 18, 8, 24, 14,
	0, 1, 0, 5, 0, 4, 20, 10,
	0, 5, 21, 11, 20, 10, 25, 15,
	0, 0, 0, 3, 0, 0, 19, 9,
	0, 3, 18, 8, 19, 9, 24, 14,
	0, 1, 0, 4, 0, 5, 20, 10,
	0, 5, 20, 10, 21, 11, 25, 15,
	0, 1, 0, 5, 0, 5, 21, 11,
	0, 4, 20, 10, 20, 10, 25, 15,
	0, 2, 0, 6, 0, 6, 22, 12,
	0, 6, 22, 12, 22, 12, 26, 16
]

"""
`all_motifs`
============

Classifies all triplets of edges in a given hypergraph into h-motifs.

Arguments
---------
    - `H::Hypergraph`: The hypergraph to analyze

Returns
-------
A 2D-array where `A[i]` is the list of triplets that are instances of h-motif `i`.
"""

function all_motifs(M::MatrixHypergraph)
	motif_inst::Vector{Vector{Tuple{Int64,Int64,Int64}}} = [[] for i = 0:26] # Initialize the motif list
	G = dyadic_projection(dual(M))
	adj = [G.ci[G.rp[i]:G.rp[i+1]-1] for i = 1:G.n] # Get which hyperedges are adjacent
	inc = M.incidence'
	m = size(inc,1)
	edges = [inc[i,:].nzind for i = 1:m] # Get the nodes involved in each hyperedge
	sizes = length.(edges)
	inters::Dict{Tuple{Int64,Int64},Vector{Int64}} = Dict((i,j) => intersect(edges[i],edges[j]) for i = 1:m for j in adj[i] if i < j) # Compute the intersection between hyperedges. This is the primary bottleneck

	for a = 1:m # Enumerate all hyperedges
		size_a = sizes[a]
		deg_a = G.rp[a+1]-G.rp[a]
		neigh = adj[a]
		for hb = 1:deg_a-1 # Only look at neighbors, so that we only consider connected triplets
			b = neigh[hb]
			if a > b break end # Only considers unique triplets
			size_b = sizes[b]
			deg_b = G.rp[b+1]-G.rp[b]

			for hc = hb+1:deg_a
				c = neigh[hc]
				size_c = sizes[c]
				deg_c = G.rp[c+1]-G.rp[c]

				if length(get(inters,(b,c),Int64[])) > 0 # Save time by not computing three-way intersection if it doesn't exist
					id = get_id(size_a,size_b,size_c,
								length(inters[(a,b)]),length(inters[(b,c)]),length(inters[(a,c)]),
								length(intersect(inters[(a,b)],edges[c]))) + 1
					push!(motif_inst[id], (a,b,c))
				else
					id = get_id(size_a,size_b,size_c,
								length(inters[(a,b)]),0,length(inters[(a,c)]),
								0)+1
					push!(motif_inst[id], (a,b,c))
				end
			end
		end
	end

	return motif_inst
end

"""
`get_id`
========

Classifies which h-motif a triplet of hyperedges is an instance of based on information
about their sizes and intersections.

Arguments
---------
	- `d_a::Int64`: The size of the first hyperedge
	- `d_b::Int64`: The size of the second hyperedge
	- `d_c::Int64`: The size of the third hyperedge
	- `i_ab::Int64`: The size of the intersection between the first two hyperedges
	- `i_bc::Int64`: The size of the intersection between the last two hyperedges
	- `i_ca::Int64`: The size of the intersection between the first and third hyperedges
	- `g_abc::Int64`: The size of the three-way intersection among all hyperedges

Returns
-------
The motif that the triplet is an instance of. Returns 0 if the motif is invalid.
The diagrams corresponding to the id's may be found on page 3 of https://arxiv.org/pdf/2003.01853.pdf.
"""
function get_id(d_a::Int64,d_b::Int64,d_c::Int64,
				i_ab::Int64,i_bc::Int64,i_ca::Int64,
				g_abc::Int64)
	a = d_a - (i_ab+i_ca) + g_abc # Number of nodes unique to first hyperedge
	b = d_b - (i_bc+i_ab) + g_abc
	c = d_c - (i_ca+i_bc) + g_abc
	d = i_ab - g_abc # Number of nodes shared only between first and second hyperedges
	e = i_bc - g_abc
	f = i_ca - g_abc
	g = g_abc # Number of nodes shared among all three

	vect = ((a > 0) << 6) + ((b > 0) << 5) + ((c > 0) << 4) + ((d > 0) << 3) +
		   ((e > 0) << 2) + ((f > 1) << 1) + ((g > 0) << 0) # Encoding the Venn diagram as a binary number
	return motif_id[vect+1] # Return the id located at that number (+1 because Julia is one-indexed)
end

"""
`motif_coocurrence`
===================

Constructs the h-motif co-occurrence matrix for a hypergraph, based on a particular
h-motif. The motif co-occurrence matrix records how many h-motif instances each
pair of nodes co-occurs in.

Arguments
---------
	- `M::MatrixHypergraph`: The hypergraph for which to create the matrix.
	- `motifs::Vector{Vector{Tuple{Int64,Int64,Int64}}}`: The classification of triplets of hyperedges
														  into h-motifs. A[i+1] is all instances of the ith motif,
														  with invalid instances occupying A[1].
	- `m::Int8`: The motif that the co-occurrence matrix is based on.

Returns
-------
A symmetric `SparseMatrix` where the ij entry is the number of instances of h-motif
`m` that nodes `i` and `j` co-occur in. If the two nodes do not share a hyperedge in
`M`, the entry will be 0.
The diagrams corresponding to the id's may be found on page 3 of https://arxiv.org/pdf/2003.01853.pdf.
"""
function motif_cooccurrence(M::MatrixHypergraph, motifs::Vector{Vector{Tuple{Int64,Int64,Int64}}}, m::Int8)
	inc = M.incidence'
	W = spzeros(Float64, size(inc,2), size(inc,2))

    for t in motifs[m+1]
		i,j,k = t
		co::Set{Set{Int64,Int64}} = Set() # Node pairs that co-occur together in the hyperedges of t
		# Only strengthen edges that already exist, and only strengthen once per motif (i.e. don't double-count edges on the overlap)
		for e in [inc[i,:].nzind, inc[j,:].nzind, inc[k,:].nzind]
			len = length(e)
	        for u = 1:len-1
				for v = u+1:len
					push!(co, (e[u],e[v]))
				end
			end
		end
		for p in co # Increase weight by one for each pair of hyperedge-sharing, motif co-occurring nodes
			W[p[1],p[2]] += 1
			W[p[2],p[1]] += 1
		end
    end
    return W
end

max_stars_repo_name: joshua-matt/HO-HyperRank

max_issues_repo_name: joshua-matt/HO-HyperRank

max_forks_repo_name: joshua-matt/HO-HyperRank


text:
function find(dirname::String, f::Function)
  if !isdir(dirname)
    error("find() can only be called on directories")
  end

  starting_dir = pwd()

  cd(dirname)

  for filename in readdir(".")
    f(abspath(filename))
    if isdir(filename) && !islink(filename)
      find(filename, f)
    end
  end

  cd(starting_dir)
end

find(dirname::String) = find(dirname, println)
find(f::Function) = find(".", f)
find() = find(".", println)


text:
#=#these map model types to model functions
optmodels = Dict{Symbol, Function}(
  :levellsq => optlevellsqmodel,
  :levellsqbb => optlevellsqbbmodel,
)=#

optresultsname(λ⁺, ::Val{:levellsq}) = "results_$(PARAM[:crspdatalabel])" *
  boundrangestr() *
  "_$(PARAM[:predictiontype])" *
  "_$(PARAM[:optresultssuffix])" *
  "_$λ⁺"

optresultsname(λ⁺, ::Val{:levellsqbb}) = "results_$(PARAM[:crspdatalabel])" *
  boundrangestr() *
  "_$(PARAM[:predictiontype])" *
  "_$(PARAM[:optresultssuffix])" *
  "_$λ⁺" *
  "_$(Dates.format(now(),"yyyymmdd_HHMMSS"))"

optresultsname(::Val{:levellsqbb}) = "results_$(PARAM[:crspdatalabel])" *
  boundrangestr() *
  "_$(PARAM[:predictiontype])" *
  "_$(PARAM[:optresultssuffix])" *
  "_$(Dates.format(now(),"yyyymmdd_HHMMSS"))"
optresultsname(λ⁺) = optresultsname(λ⁺, Val(PARAM[:optmodel]))
optresultsname() = optresultsname(Val(PARAM[:optmodel]))
#primary function for estimating the measure using optimizations
#note that this still uses the same volume parts construct as flux
function formoptregression(panel::DataFrame, ms::MeasureSpec,
  OptModel::Val = Val(PARAM[:optmodel]))

  issorted(panel, [:permno, :date]) || error("panel must be sorted")

  #in contrast to other methods, drop any column where we don't have
  #the lag weight (improves performance I think)

  #conditionforturing!(panel::SubDataFrame, ms::MeasureSpec)

  zs::ZSpec = condition!(panel, ms)

  #testing
  if PARAM[:testmeasure]
    testdlsq(panel, zs.Zms)
  end

  if PARAM[:refreshmeasure]
    λ⁺, results::DataFrame = optmodel(panel, zs, OptModel)
    destandardize!(results, zs)

    #this will be the name of the results file
    resultname::String = optresultsname(λ⁺)

    results |> CSV.write("$(PARAM[:outputpath])\\$(resultname).csv")

  end

end

#mostly taken from /BlackBoxOptim.jl/src/opt_controller.jl

mutable struct BBAdditionalState
  lastresid::Float64
  lasttime::Float64
  besttime::Float64
  timesincebest::Float64
  stepssincebest::Int
  stopnoimprovement::Float64
end

function BBAdditionalState()
  lastresid=Inf
  lasttime=0
  stepssincebest=0
  besttime = 0.0
  timesincebest=0.0
  stopnoimprovement=PARAM[:optbbstopnoimprovement]

  return   BBAdditionalState(lastresid, lasttime, besttime, timesincebest, stepssincebest, stopnoimprovement)
end

function bbcallback(op, rΨ::Ref{BBAdditionalState})
  t = BlackBoxOptim.elapsed_time(op)
  if t < rΨ[].lasttime #special case when comparing multiple models
    rΨ[] = BBAdditionalState() #reinitialize
  end
  Ψ::BBAdditionalState = rΨ[]

  steps::Int = BlackBoxOptim.num_steps(op)
  stepsps = steps/t
  resid = BlackBoxOptim.best_fitness(op)
  stepssincelast = op.num_steps_since_last_report
  Δnumbetter = op.num_better_since_last_report

  if resid < Ψ.lastresid #this means we found a new best solution
    Ψ.lastresid = resid
    Ψ.besttime = t
    Ψ.timesincebest=0.0
    Ψ.stepssincebest = 0
  else
    Ψ.stepssincebest += stepssincelast
    Ψ.timesincebest = t - Ψ.besttime
  end
  Ψ.lasttime=t
  #reset the built-in state
  op.num_better_since_last_report = 0
  op.num_steps_since_last_report = 0

  form(x) = round(x, digits=1)
  @info ("t=$(form(t))s, steps=$steps, steps/s=$(form(stepsps)) ," *
    " resid=$(form(resid)), Δimprovsteps=$Δnumbetter, stepssincebest=$(Ψ.stepssincebest)" *
    " timesincebest=$(form(Ψ.timesincebest))")

  #BlackBoxOptim.shutdown_optimizer!(op)
  if Ψ.timesincebest > Ψ.stopnoimprovement
    BlackBoxOptim.shutdown_optimizer!(op)
  end

  return nothing
end

function optbbestimate(::Type{T}=PARAM[:opttype],
    ::Type{TV}=PARAM[:optgpu] ? CUDA.CuVector{T} : Vector{T},
    ::Type{TM}=PARAM[:optgpu] ? CUDA.CuMatrix{T} : Matrix{T};
  bounds=error("bounds (tuple or Vector of tuples) is required"),
  loss::Function = error("loss function is required"),
  Θ::AbstractVolumeParts = error("original vol parts model is required"),
  X::NamedTuple = error("X is required"),
  y::TV = error("y is required"),
  bbalg::Symbol = PARAM[:optbbalg],
  maxtime::Float64 = PARAM[:optbbmaxtime],
  reportinterval = PARAM[:optbbreportinterval],
  ) where {
    T<:Real, TV<:AbstractVector{T}, TM<:AbstractMatrix{T}}

  rΨ::Ref{BBAdditionalState} = Ref(BBAdditionalState())

  opt=bboptimize(loss,
    SearchRange=bounds,
    Method=bbalg,
    MaxTime=maxtime,
    TraceMode=:silent,
    CallbackFunction=(op)->bbcallback(op, rΨ),
    CallbackInterval = reportinterval)

  return opt, rΨ[]
end

#this function writes information about the simulation run
function optbbresults(::Type{T}=PARAM[:opttype];
    loss=error("loss function is required"),
    opt=error("opt is required"),
    Ψ::BBAdditionalState=error("Ψ is required"),
    Θ::AbstractVolumeParts=error("Θ is required"),
    Θver::AbstractVolumeParts=error("Θver (AD-valid Θ) is required"),
    X::NamedTuple=error("X is required"),
    y::AbstractVector=error("y is required")) where T<:Real

  dims = (T=size(Θ.A,2), K=size(Θ.A,1))
  λ⁺ = loss(Θ, X,y)

  b = IOBuffer()
  write(b, "***Results info:\n" *
    "iterations: $(opt.iterations)\n" *
    "start_time: $(opt.start_time)\n" *
    "time_to_completion: $(opt.start_time)\n" *
    "maxtime: $(PARAM[:optbbmaxtime])\n" *
    "time since best: ~$(Ψ.timesincebest)\n" *
    "steps since best: ~$(Ψ.stepssincebest)\n" *
    "Best resid: $λ⁺\n")

  write(b, "\n\n***Other Simulation parameters:\n" *
    "method: $(opt.method)\n" *
    "stop_reason (if not timesincebest): $(opt.stop_reason)\n" *
    "report interval: $(PARAM[:optbbreportinterval])\n" *
    "eval many models: $(PARAM[:optbbcomparemodels])")
  #compute the full jacobian with AD

  ∇Θver = gradient(()->loss(Θver,X,y),Flux.params(Θver))
  rmsver = sqrt(mean(vec∇(Θver, ∇Θver).^2))

  write(b, "\n\nlst squares gradient rms: $rmsver\n")

  optinfo = String(take!(b))
  println(optinfo)
  open("$(PARAM[:outputpath])\\$(optresultsname(λ⁺))_info.txt", "w+") do f
    write(f, optinfo)
  end

  return nothing
end

function optbbcomparemodels(::Type{T}=PARAM[:opttype],
    ::Type{TV}=PARAM[:optgpu] ? CUDA.CuVector{T} : Vector{T},
    ::Type{TM}=PARAM[:optgpu] ? CUDA.CuMatrix{T} : Matrix{T};
  bounds=error("bounds (tuple or Vector of tuples) is required"),
  loss::Function = error("loss function is required"),
  Θ::AbstractVolumeParts = error("original vol parts model is required"),
  X::NamedTuple = error("X is required"),
  y::TV = error("y is required"),
  maxtime::Float64 = PARAM[:optbbmaxtime],
  reportinterval = PARAM[:optbbreportinterval],
  comparealgs::Vector{Symbol} = PARAM[:comparealgs])   where {
      T<:Real, TV<:AbstractVector{T}, TM<:AbstractMatrix{T}}

  rΨ::Ref{BBAdditionalState} = Ref(BBAdditionalState())

  #make sure all of the methods we are going to run are valid
  for alg ∈ comparealgs
    @assert haskey(BlackBoxOptim.SingleObjectiveMethods, alg)
  end

  maxtime>1800 && error("$maxtime too high given that evalmodels=true")

  results = compare_optimizers(loss,
    SearchRange=bounds,
    MaxTime=maxtime,
    TraceMode=:silent,
    CallbackFunction=(op)->bbcallback(op, rΨ),
    CallbackInterval = reportinterval,
    Methods=comparealgs)

  #this section is based on code at  BlackBoxOptim.jl/src/compare_optimizers.jl
  sorted = sort(results, by = (t) -> t[4])
  comparedf = DataFrame(N=1:length(sorted),
    method=(v->v[1]).(sorted),
    status=(v->v[2]).(sorted),
    fitness=(v->v[4]).(sorted),
    time = (v->v[5]).(sorted))

  comparedf|>CSV.write("$(PARAM[:outputpath])\\$(optresultsname())_compare.csv")

end

max_stars_repo_name: clintonTE/CCA

max_issues_repo_name: clintonTE/CCA

max_forks_repo_name: clintonTE/CCA


text:
"""
    process_pokes(filepath::String)

Given a path of flipping data it preprocess the main variables such as Trial and Block. To deal with the different formats of raw data
collect over the year it checks the presence of a set of preexisting column
"""

function process_pokes(filepath::String)
    df = CSV.read(filepath, DataFrame)
    if !iscolumn(df,:Poke)
        DataFrames.rename!(df, propertynames(df)[1] => :Poke) #change poke counter name
    end
    if iscolumn(df,:delta)
        DataFrames.rename!(df, :delta => :Delta)
    end
    df[!,:Poke] = df[!,:Poke].+1
    start_time = df[1,:PokeIn]
    df[!,:PokeIn] = df[!,:PokeIn] .- start_time
    df[!,:PokeOut] = df[!,:PokeOut] .- start_time
    df[!,:PokeDur] = df[!,:PokeOut] - df[!,:PokeIn]
    if !iscolumn(df,:Wall)
        df[:,:Wall] = zeros(size(df,1))
    end
    booleans=[:Reward,:Side,:SideHigh,:Stim,:Wall]#columns to convert to Bool
    for x in booleans
        if df[1,x] isa AbstractString
                df[!,x] = parse.(Bool,df[!,x])
        elseif df[1,x] isa Real
            df[!,x] = Bool.(df[:,x])
        end
    end
    df[!,:Side] = [a ? "L" : "R" for a in df[!,:Side]]
    if iscolumn(df,:ProbVec0)
        integers=[:Protocollo,:ProbVec0,:ProbVec1,:GamVec0,:GamVec1,:Delta]; #columns to convert to Int64
        for x in integers
            df[!,x] = Int64.(df[!,x])
        end
        df[!,:Protocol] = [r.Protocollo == 0 ? string(r.ProbVec0,"/",r.GamVec0) : string(r.ProbVec1,"/",r.GamVec1) for r in eachrow(df)]
        for x in[:ProbVec0,:ProbVec1,:GamVec0,:GamVec1,:Protocollo]
            DataFrames.select!(df,DataFrames.Not(x))
        end
        if !iscolumn(df,:StimFreq)
            df[!,:StimFreq] .= 10000
        end
        df[!,:StimFreq] = [a == 10000 ? 25 : a  for a in df[!,:StimFreq]]
        df[!,:Box] .= "Box0"
    elseif iscolumn(df,:Prwd)
        df[!,:Protocol] = string.(df[!,:Prwd],'/',df[!,:Ptrs])
        df[!,:Box] = "Box".*string.(df[:,:Box])
    end
    df[!,:StimDay] .= length(findall(df[:,:Stim])) == 0 ? false : true
    df[!,:Leave] = lead(check_changes(df[:,:Side]), default = false)
    df[!,:Bout] = count_different(df.Reward .| check_changes(df.Side))
    df[!,:Streak] = count_different(check_changes(df[:,:Side]))
    df[!,:ReverseStreak] = reverse(df[:,:Streak])
    df[!,:PokeInStreak] .= 0
    df[!,:PokeHierarchy] .= 0.0
    df[!,:PokeInStreak] = Vector{Union{Float64,Missing}}(undef,size(df,1))
    df[!,:PreInterpoke] = Vector{Union{Float64,Missing}}(undef,size(df,1))
    df[!,:PostInterpoke] = Vector{Union{Float64,Missing}}(undef,size(df,1))
    combine(groupby(df,:Streak)) do dd
        dd[:,:PokeInStreak] = count_different(check_changes(dd[!,:Poke]))
        dd[:,:PreInterpoke] =  dd[!,:PokeIn] .-lag(dd[!,:PokeOut],default = missing)
        dd[:,:PostInterpoke] = lead(dd[!,:PokeIn],default = missing).- dd[!,:PokeOut]
        dd[:,:PokeHierarchy] = get_hierarchy(dd[!,:Reward])
    end
    df[!,:Block] = count_different(check_changes(df[!,:Wall]))
    df[!,:StreakInBlock] .= 0
    combine(groupby(df,:Block)) do dd
        dd[:,:StreakInBlock] = count_different(check_changes(dd[!,:Side]))
    end
    df[!,:SideHigh] = [x ? "L" : "R" for x in df[!,:SideHigh]]
    df[!,:Correct] = df[!,:Side] .== df[!,:SideHigh]
    return df[:, [:Poke,:Side,:SideHigh, :Correct,
    :Reward, :PokeHierarchy, :PokeInStreak,
    :Leave, :Bout, :Streak, :Stim, :StimFreq, :Wall, :Block, :StreakInBlock,
    :Delta, :Protocol, :Box, :StimDay,
    :PokeIn, :PokeOut, :PokeDur, :PreInterpoke, :PostInterpoke,:ReverseStreak]]
end


text:
using Documenter, PiCraft
using Literate

examples = ["safeFeet", "turnToGold", "turtle", "skyscraperBasic", "GameOfLife",
            "platform9_75"]

for eg in examples
    file_path = "../example/" * eg * ".jl"
    out_path = "src/example"
    Literate.markdown(file_path, out_path; documenter=false, execute=false)
end

makedocs(
   modules = [PiCraft],
   format = Documenter.HTML(prettyurls = get(ENV, "CI", nothing) == "true"),
   clean = true,
   sitename = "PiCraft",
   pages = Any[
       "Home" => "index.md",
       "Quick Start" => Any[
            "Installation" => "installation.md",
            "Connecting" => "connecting.md",
            "Coordinate System" => "coordinateSystem.md",
            "Blocks and Models" => "blocksAndModels.md",
            "Events, Entities and Camera" => "eventsEntitiesCamera.md"
       ],
       "Examples" => Any[
            "Safe Feet" => "example/safeFeet.md",
            "Turn to Gold" => "example/turnToGold.md",
            "Turtle" => "example/turtle.md",
            "Sky Scraper" => "example/skyscraperBasic.md",
            "Game Of Life" => "example/GameOfLife.md",
            "Platform 9¾" => "example/platform9_75.md",
            "Whac-a-Block" => "whacABlock.md"
       ],
       "Block Reference" => "blocks.md",
       "API Reference" => "api.md"
   ]
)

deploydocs(
    repo = "github.com/aviks/PiCraft.jl.git",
    target = "build",
    deps = nothing,
    make = nothing,
)


text:
using LightGraphs: LightGraphs, DiGraph, add_edge!, add_vertex!, has_edge, nv

struct Hierarchy <: Graph
    g::DiGraph
    N::Vector{Symbol}
    I::Dict{Symbol,Int}
    E::Dict{NTuple{2,Int},Symbol}
    C::Dict{Symbol,Any}
end

hierarchy(C=()) = Hierarchy(DiGraph(), Symbol[], Dict{Symbol,Int}(), Dict{NTuple{2,Int},Symbol}(), Dict{Symbol,Any}(C))
hierarchy(S::Type{<:System}; kw...) = begin
    h = hierarchy(kw)
    add!(h, S)
    h
end
hierarchy(::S; kw...) where {S<:System} = hierarchy(S; kw...)

graph(h::Hierarchy) = h.g

node!(h::Hierarchy, n::Symbol) = begin
    if !haskey(h.I, n)
        add_vertex!(h.g)
        h.I[n] = nv(h.g)
    end
    n
end
node!(h::Hierarchy, T::Type{<:System}) = node!(h, namefor(T))

using DataStructures: SortedDict
nodes(h::Hierarchy) = SortedDict(v => k for (k, v) in h.I) |> values |> collect

hasloop(h::Hierarchy, n::Symbol) = (i = h.I[n]; has_edge(h.g, i, i))

link!(h::Hierarchy, a::Symbol, b::Symbol, e=nothing) = begin
    ai = h.I[a]
    bi = h.I[b]
    add_edge!(h.g, ai, bi)
    (ai == bi) && (e = :loop)
    !isnothing(e) && (h.E[(ai, bi)] = e)
end

add!(h::Hierarchy, S::Type{<:System}) = begin
    #HACK: evaluation scope is the module where S was originally defined
    scope = S.name.module
    a = node!(h, S)
    (a in h.N || hasloop(h, a)) && return
    add!(h, a, mixinsof(S))
    V = geninfos(S)
    for v in V
        T = @eval scope $(v.type)
        #HACK: skip Context since the graph tends to look too busy
        get(h.C, :skipcontext, false) && (T == typefor(Context)) && continue
        add!(h, a, T)
    end
    push!(h.N, a)
end

add!(h::Hierarchy, a::Symbol, M::Tuple) = begin
    for m in M
        (m == System) && continue
        add!(h, m)
        b = node!(h, m)
        link!(h, b, a, :mixin)
    end
end
add!(h::Hierarchy, a::Symbol, T::Type{<:System}) = begin
    b = node!(h, T)
    link!(h, b, a)
    add!(h, T)
end
add!(h::Hierarchy, a::Symbol, T::Type{Vector{S}}) where {S<:System} = add!(h, a, S)
add!(h::Hierarchy, a::Symbol, T) = nothing

label(n::Symbol) = string(n)
labels(h::Hierarchy; kw...) = label.(nodes(h))

edgestyle(h::Hierarchy, e::Symbol) = begin
    if e == :mixin
        "dashed"
    elseif e == :loop
        "loop"
    else
        "solid"
    end
end
edgestyles(h::Hierarchy; kw...) = Dict(e => edgestyle(h, s) for (e, s) in h.E)

Base.show(io::IO, h::Hierarchy) = print(io, "Hierarchy")
Base.show(io::IO, ::MIME"text/plain", h::Hierarchy) = begin
    color = get(io, :color, false)
    SC = tokencolor(SystemColor(); color)
    MC = tokencolor(MiscColor(); color)
    print(io, MC("{"))
    print(io, join(SC.(labels(h)), MC(", ")))
    print(io, MC("}"))
end


text:
using Test

N = 100
kmax = 3
edges = 1000
sampler = ER_sampler(N, kmax)

graph = rand(sampler, edges)

for i in graph
    #println(i)
end

@testset "shape" begin
    @test length(graph) == edges
    @test all(length.(graph) .== kmax)
end

max_stars_repo_name: LilithHafner/FBD

max_issues_repo_name: LilithHafner/FBD

max_forks_repo_name: LilithHafner/FBD


text:
"""
    Multivector4{T <: Real} <: AbstractMultivector{T}

An immutable 16-tuple of real numbers that represents a member
of a 4-dimensional multivector algebra.

Each `Multivector4` has the form
```math
    p+qD
```
where ``p`` and ``q`` are 3-dimensional multivectors.
"""
struct Multivector4{T <: Real} <: AbstractMultivector{T}
    l::Multivector3{T}
    r::Multivector3{T}

    Multivector4{U}(l::Multivector3{U}, r::Multivector3{U}) where {U <: Real} = new(l, r)
end

function Multivector4(x::Multivector3{T}, y::Multivector3{T}) where {T <: Real}
    Multivector4{T}(x, y)
end

function Multivector4(x::Multivector3)
    Multivector4(x, zero(x))
end

function Multivector4(x::Multivector2)
    Multivector4(Multivector3(x), Multivector3(zero(x)))
end

function Multivector4(x::Multivector1)
    Multivector4(Multivector3(x), Multivector3(zero(x)))
end

function show(io::IO, z::Multivector4)
    print(io, "[1: ")
    print(io, z.l.l.l.l)
    print(io, ", A: ")
    print(io, z.l.l.l.r)
    print(io, ", B: ")
    print(io, z.l.l.r.l)
    print(io, ", AB: ")
    print(io, z.l.l.r.r)
    print(io, ", C: ")
    print(io, z.l.r.l.l)
    print(io, ", AC: ")
    print(io, z.l.r.l.r)
    print(io, ", BC: ")
    print(io, z.l.r.r.l)
    print(io, ", (AB)C: ")
    print(io, z.l.r.r.r)
    print(io, ", D: ")
    print(io, z.r.l.l.l)
    print(io, ", AD: ")
    print(io, z.r.l.l.r)
    print(io, ", BD: ")
    print(io, z.r.l.r.l)
    print(io, ", (AB)D: ")
    print(io, z.r.l.r.r)
    print(io, ", CD: ")
    print(io, z.r.r.l.l)
    print(io, ", (AC)D: ")
    print(io, z.r.r.l.r)
    print(io, ", (BC)D: ")
    print(io, z.r.r.r.l)
    print(io, ", ((AB)C)D: ")
    print(io, z.r.r.r.r)
    print(io, "]")
end

function real(z::Multivector4)
    real(z.l)
end

function unreal(z::Multivector4)
    vcat(unreal(z.l), asarray(z.r))
end

function zero(z::Multivector4{T}) where {T <: Real}
    Multivector4{T}(zero(z.l), zero(z.r))
end

function zero(::Type{Multivector4{T}}) where {T <: Real}
    Multivector4{T}(zero(T))
end

function one(z::Multivector4{T}) where {T <: Real}
    Multivector4{T}(one(z.l))
end

function one(::Type{Multivector4{T}}) where {T <: Real}
    Multivector4{T}(one(T))
end

"""
    conj{T <: Real}(z::Multivector4{T})

The `Multivector4` conjugate.
This operation is an involution.
"""
function conj(z::Multivector4{T}) where {T <: Real}
    Multivector4{T}(conj(z.l), -z.r)
end

"""
    cloak{T <: Real}(z::Multivector4{T})

The cloak conjugate changes the sign of even blades.
This operation is equivalent to `-dagger(z)` and thus is also an involution.
"""
function cloak(z::Multivector4{T}) where {T <: Real}
    Multivector4{T}(cloak(z.l), dagger(z.r))
end

"""
    dagger{T <: Real}(z::Multivector4{T})

The dagger conjugate changes the sign of odd blades.
This operation is an involution.
"""
function dagger(z::Multivector4{T}) where {T <: Real}
    Multivector4{T}(dagger(z.l), cloak(z.r))
end

"""
    star{T <: Real}(z::Multivector4{T})

Returns the Hodge star conjugate.
This operation is not an involution, but `star(star(z)) = dagger(z)`.
"""
function star(z::Multivector4{T}) where {T <: Real}
    Multivector4{T}(dagger(star(z.r)), star(z.l))
end

"""
    selfstar(z::Multivector4)

The self-star-conjugate part.
This operation is idempotent.
"""
function selfstar(z::Multivector4)
    (z + star(z) + dagger(z) + star(dagger(z))) / 4
end

"""
    antiselfstar(z::Multivector4)

The anti-self-star-conjugate part.
This operation is idempotent.
"""
function antiselfstar(z::Multivector4)
    (z - star(z) + dagger(z) - star(dagger(z))) / 4
end

function (+)(x::Multivector4, y::Multivector4)
    Multivector4(x.l + y.l, x.r + y.r)
end

function (+)(x::Multivector4, y::Multivector3)
    Multivector4(x.l + y, x.r)
end

function (+)(x::Multivector3, y::Multivector4)
    Multivector4(x + y.l, y.r)
end

function (+)(x::Multivector4, y::Multivector2)
    Multivector4(x.l + y, x.r)
end

function (+)(x::Multivector2, y::Multivector4)
    Multivector4(x + y.l, y.r)
end

function (+)(x::Multivector4, y::Multivector1)
    Multivector4(x.l + y, x.r)
end

function (+)(x::Multivector1, y::Multivector4)
    Multivector4(x + y.l, y.r)
end

function (+)(z::Multivector4, a::Real)
    Multivector4(z.l + a, z.r)
end

function (+)(a::Real, z::Multivector4)
    Multivector4(z.l + a, z.r)
end

function (-)(z::Multivector4{T}) where {T <: Real}
    Multivector4{T}(-z.l, -z.r)
end

function (-)(x::Multivector4, y::Multivector4)
    Multivector4(x.l - y.l, x.r - y.r)
end

function (-)(x::Multivector4, y::Multivector3)
    Multivector4(x.l - y, x.r)
end

function (-)(x::Multivector3, y::Multivector4)
    Multivector4(x - y.l, -y.r)
end

function (-)(x::Multivector4, y::Multivector2)
    Multivector4(x.l - y, x.r)
end

function (-)(x::Multivector2, y::Multivector4)
    Multivector4(x - y.l, -y.r)
end

function (-)(x::Multivector4, y::Multivector1)
    Multivector4(x.l - y, x.r)
end

function (-)(x::Multivector1, y::Multivector4)
    Multivector4(x - y.l, -y.r)
end

function (-)(z::Multivector4, a::Real)
    Multivector4(z.l - a, z.r)
end

function (-)(a::Real, z::Multivector4)
    Multivector4(a - z.l, -z.r)
end

"""
    (*)(x::Multivector4, y::Multivector4)

Wedge product of 4-dimensional multivectors.
This operation is non-commutative and non-associative.
"""
function (*)(x::Multivector4, y::Multivector4)
    Multivector4(x.l * y.l,  (y.r * x.l) + (x.r * conj(y.l)))
end

function (*)(x::Multivector4, y::Multivector3)
    Multivector4(x.l * y, x.r * conj(y))
end

function (*)(x::Multivector3, y::Multivector4)
    Multivector4(x * y.l,  y.r * x)
end

function (*)(x::Multivector4, y::Multivector2)
    Multivector4(x.l * y, x.r * conj(y))
end

function (*)(x::Multivector2, y::Multivector4)
    Multivector4(x * y.l,  y.r * x)
end

function (*)(x::Multivector4, y::Multivector1)
    Multivector4(x.l * y, x.r * conj(y))
end

function (*)(x::Multivector1, y::Multivector4)
    Multivector4(x * y.l,  y.r * x)
end

"""
    (*)(z::Multivector4, a::Real)
    (*)(a::Real, z::Multivector4)

Scaling and/or reflection of a `Multivector4` by a real number.
"""
function (*)(z::Multivector4, a::Real)
    Multivector4(z.l * a, z.r * a)
end

function (*)(a::Real, z::Multivector4)
    Multivector4(a * z.l, a * z.r)
end

function (/)(x::Multivector4, y::Multivector4)
    if iszerodivisor(y)
        error(ZeroDivisorDenominator)
    end

    x * inv(y)
end

function (\)(y::Multivector4, x::Multivector4)
    if iszerodivisor(y)
        error(ZeroDivisorDenominator)
    end

    inv(y) * x
end

function (/)(z::Multivector4, a::Real)
    Multivector4(z.l / a, z.r / a)
end

function (\)(a::Real, z::Multivector4)
    Multivector4(a \ z.l, a \ z.r)
end

function random(::Type{Multivector4{T}}) where T <: Real
    Multivector4{T}(random(Multivector3{T}), random(Multivector3{T}))
end