text:
#=

  Global constraint global contiguity regular in Julia ConstraintSolver.jl

  From Global Constraint Catalogue
  http://www.emn.fr/x-info/sdemasse/gccat/Cglobal_contiguity.html
  """
  Enforce all variables of the VARIABLES collection to be assigned to 0 or 1.
  In addition, all variables assigned to value 1 appear contiguously.

  Example:
  (<0,1,1,0>)

  The global_contiguity constraint holds since the sequence 0 1 1 0 contains
  no more than one group of contiguous 1.
  """

  Here's a variant of the global constraint global contiguity
  using (a decomposition of) the regular constraint.

  For n=0:13 the number of solutions is
  [1, 2, 4, 7, 11, 16, 22, 29, 37, 46, 56, 67, 79]

  Which is the (or rather one of the possible) OEIS sequence https://oeis.org/A000124
  """
  Central polygonal numbers (the Lazy Caterer's sequence): n(n+1)/2 + 1; or,
  maximal number of pieces formed when slicing a pancake with n cuts.
  """

  Model created by Hakan Kjellerstrand, hakank@gmail.com
  See also my Julia page: http://www.hakank.org/julia/

=#
using ConstraintSolver, JuMP
using Cbc, GLPK, Ipopt
const CS = ConstraintSolver
include("constraints_utils.jl")

function global_contiguity_test(n,print_solutions=true,all_solutions=true)

    cbc_optimizer = optimizer_with_attributes(Cbc.Optimizer, "logLevel" => 0)
    glpk_optimizer = optimizer_with_attributes(GLPK.Optimizer)
    ipopt_optimizer = optimizer_with_attributes(Ipopt.Optimizer)

    model = Model(optimizer_with_attributes(CS.Optimizer,   "all_solutions"=> all_solutions,
                                                            # "all_optimal_solutions"=>all_solutions,
                                                            "logging"=>[],

                                                            "traverse_strategy"=>:BFS,
                                                            # "traverse_strategy"=>:DFS,
                                                            # "traverse_strategy"=>:DBFS,

                                                            # "branch_split"=>:Smallest,
                                                            # "branch_split"=>:Biggest,
                                                            "branch_split"=>:InHalf,

                                                            # https://wikunia.github.io/ConstraintSolver.jl/stable/options/#branch_strategy-(:Auto)
                                                            "branch_strategy" => :IMPS, # default
                                                            # "branch_strategy" => :ABS, # Activity Based Search
                                                            # "activity.decay" => 0.999, # default 0.999
                                                            # "activity.max_probes" => 10, # default, 10
                                                            # "activity.max_confidence_deviation" => 20, # default 20

                                                            # "simplify"=>false,
                                                            # "simplify"=>true, # default

                                                            "time_limit"=>6,

                                                            # "backtrack" => false, # default true
                                                            # "backtrack_sorting" => false, # default true

                                                            # "lp_optimizer" => cbc_optimizer,
                                                            # "lp_optimizer" => glpk_optimizer,
                                                            # "lp_optimizer" => ipopt_optimizer,
                                        ))

    @variable(model, x[1:n], Bin)

    y = global_contiguity_regular(model, x)

    # Solve the problem
    optimize!(model)

    status = JuMP.termination_status(model)
    # println("status:$status")
    num_sols = 0
    if status == MOI.OPTIMAL
        num_sols = MOI.get(model, MOI.ResultCount())
        println("num_sols:$num_sols\n")
        if print_solutions
            for sol in 1:num_sols
                println("solution #$sol")
                x_val = convert.(Integer,JuMP.value.(x; result=sol))
                y_val = convert.(Integer,JuMP.value.(y; result=sol))
                println("x:$x_val")
                println("y:$y_val")
                println()

            end
        end
    else
        println("status:$status")
    end

    return status, num_sols
end

sols = []
for n in 0:13
    global sols
    @time status, num_sols = global_contiguity_test(n,true,true)
    if status == MOI.OPTIMAL
        push!(sols,num_sols)
    end
end
println("\nsols:$sols")

# @time global_contiguity_test(10,true,true)

max_stars_repo_name: Wikunia/hakank

max_issues_repo_name: Wikunia/hakank

max_forks_repo_name: Wikunia/hakank


text:
Core.eval(Main, quote
    hello_from_sideeffect = rand()
end)

ext: jl


text:
	function sampleBSF_G!(Posterior::PosteriorSample, genetic_effects::GeneticEffects,
	                      Factors::LatentFactors, resid::Residuals,
	                      interaction_effects::InteractionEffects, fixed_effects::FixedEffects,
	                      D::InputData, Pr::Priors)
	    #precalculate some matrices
	    #invert the random effect covariance matrices
	    Ainv = inv(D.A)
	    A_2_inv = Matrix{Int}(I, D.n, D.n); #Z_2 random effects are assumed to have covariance proportional to the identity. Can be modified.

	    #pre-calculate transformation parameters to diagonalize aI + bZAZ for fast
	    #inversion: inv(aI + bZAZ) = 1/b*u*diag(1./(s+a/b))*u'
	    #uses singular value decomposition of ZAZ for stability when ZAZ is low
	    #rank()
	    # eig_ZAZ.vectors = u; -> eig_ZAZ.U
	    # eig_ZAZ.values = diag(s); -> eig_ZAZ.S

	    ZAZ = D.Z_1' * D.A * D.Z_1;
	    eig_ZAZ = svd(ZAZ);

	    Design=[D.X; D.Z_1];
	    Design2 = Design * Design';
	    svd_Design_Ainv = makeSVDdict(Array(BlockDiagonal([fixed_effects.cov, Ainv])), Design2);
	    Qt_Design = svd_Design_Ainv["Q"]' * Design;

	    #fixed effects + random effects 1
	    #diagonalize mixed model equations for fast inversion:
	    #inv(a*blkdiag(fixed_effects.cov,Ainv) + b*[X Z_1]"[X Z_1]'') = Q*diag(1./(a.*s1+b.*s2))*Q"
	    #inv(Array(BlockDiagonal([fixed_effects.cov, Ainv])) + Design2) ≈ svd_Design_Ainv["Q"] * Diagonal(1. ./ (svd_Design_Ainv["s1"]+svd_Design_Ainv["s2"])) * svd_Design_Ainv["Q"]'

	    #random effects 2
	    #as above; but for random effects 2. Here; fixed effects will be conditioned on; not sampled simultaneously. Otherwise identical.
	    if(D.r2 > 1)
	        Design_Z2 = Z_2
	        Design2_Z2 = Design_Z2*Design_Z2'
	        svd_Z2_2_A2inv = makeSVDdict(A_2_inv, Design2_Z2)
	        Qt_Z2 = svd_Z2_2_A2inv["Q"]'*Design_Z2
	    end

	    #genetic effect variances of factor traits
	    # diagonalizing a*Z_1*Z_1' + b*Ainv for fast inversion
	    #diagonalize mixed model equations for fast inversion:
	    # inv(a*Z_1*Z_1" + b*Ainv) = Q*diag(1./(a.*s1+b.*s2))*Q'
	    #similar to fixed effects + random effects 1 above; but no fixed effects.
	    ZZt = D.Z_1 * D.Z_1'
	    svd_ZZ_Ainv = makeSVDdict(ZZt, Array(Ainv))
	    # inv(Array(ZZt) + Array(Ainv)) ≈ svd_ZZ_Ainv["Q"] * Diagonal(1. ./ (svd_ZZ_Ainv["s1"]+svd_ZZ_Ainv["s2"])) * svd_ZZ_Ainv["Q"]'

	    sp_num=0
	    @showprogress 1 "Running Gibbs sampler..." for i = 1:Pr.nrun

	        ##fill in missing phenotypes
	        ##conditioning on everything else()
	        #phenMissing = isnan(Y_full)
	        #if sum(sum(phenMissing))>0
	        #    meanTraits = fixed_effects.B*X +  genetic_effects.d*Z_1 ...
	        #        + interaction_effects.W*Z_2 + Factors.Lambda*Factors.scores
	        #    meanTraits = meanTraits';
	        #    resids = bsxfun[@times,randn(size(Y_full)),1./sqrt(resid.ps')]
	        #    Y[phenMissing] = meanTraits[phenMissing] + resids[phenMissing]
	        #end

	        #sample Lambda
	        #conditioning on W; X; F; marginalizing over D
	        Ytil = D.Y' - fixed_effects.B * D.X - interaction_effects.W * D.Z_2
	        sample_lambda!(Factors, Ytil, resid, genetic_effects, eig_ZAZ)

	        #sample fixed effects + random effects 1 [[B D]']
	        #conditioning on W; F; L
	        Ytil = D.Y' - interaction_effects.W * D.Z_2 - Factors.Lambda*Factors.scores
	        N = genetic_effects.n + fixed_effects.b
	        location_sample = sample_means(Ytil, Qt_Design, N, resid, genetic_effects.ps, svd_Design_Ainv)
	        fixed_effects.B = location_sample[:,1:fixed_effects.b]
	        genetic_effects.d = location_sample[:, fixed_effects.b+1 : fixed_effects.b+genetic_effects.n ]

	        #sample random effects 2
	        #conditioning on B; D; F; L
	        N = interaction_effects.n
	        if N>0
	            Ytil = D.Y'-fixed_effects.B * D.X - genetic_effects.d * D.Z_1 - Factors.Lambda * Factors.scores
	            location_sample = sample_means(Ytil, Qt_Z2, N, resid, interaction_effects.ps, svd_Z2_2_A2inv)
	            interaction_effects.W = location_sample
	        end

	        #sample factor h2
	        #conditioning on F; marginalizing over U
	        sample_h2s_discrete!(Factors, eig_ZAZ)

	        #sample genetic effects [U]
	        #conditioning on F; Factor h2
	        sample_Us!(Factors, genetic_effects, svd_ZZ_Ainv, D.Z_1)

	        #sample F
	        #conditioning on U; Lambda; B; D; W; factor h2s
	        Ytil = D.Y' - fixed_effects.B * D.X - genetic_effects.d * D.Z_1 - interaction_effects.W * D.Z_2
	        sample_factors_scores!(Ytil, Factors, resid, genetic_effects, D.Z_1)

	        # -- Update ps -- #
	        Lambda2 = Factors.Lambda .^ 2
	        as_p = Factors.df/2. + 0.5
	        bs_p = 2. ./ (Factors.df .+ broadcast(*, Lambda2, Factors.tauh'))
	        for i = 1:D.p, j = 1:Factors.k
	            Factors.psijh[i, j] = rand(Gamma(as_p, bs_p[i, j]))
	        end

	        #continue from previous Y residual above
	        Ytil = Ytil - Factors.Lambda * Factors.scores
	        inv_bs = 1. ./ (resid.bs .+ 0.5 * sum(Ytil .^ 2, dims=2)) #model residual precision
	        for i = 1:D.p
	            resid.ps[i] = rand(Gamma(resid.as + 0.5 * D.n, inv_bs[i]))
	        end

	        #random effect 1 [D] residual precision
	        inv_b_g = 1. ./ (genetic_effects.bs .+ 0.5 * sum(genetic_effects.d .^ 2, dims=2))
	        for i = 1:D.p
	         genetic_effects.ps[i] = rand(Gamma(genetic_effects.as + 0.5 * genetic_effects.n, inv_b_g[i]))
	        end

	        #n = interaction_effects.n
	        #interaction_effects.ps=gamrnd[interaction_effects.as + 0.5*n,1./(interaction_effects.bs+0.5*sum(interaction_effects.W.^2,dims=2))]; #random effect 2 [W] residual precision

	        #------Update delta & tauh------#
	        sample_delta!(Factors, Lambda2)

	        #---update precision parameters----#
	        Factors.Plam = broadcast(*, Factors.psijh, Factors.tauh')

	        # ----- adapt number of factors to samples ----#
	        update_k!( Factors, genetic_effects, Pr.b0, Pr.b1 ,i , Pr.epsilon, Pr.prop, D.Z_1 )

	        # -- save sampled values [after thinning] -- #
	        if i%Pr.thin==0 && i > Pr.burn
	            sp_num = Int64((i-Pr.burn)/Pr.thin)
	            save_posterior_samples!(sp_num, Pr, D, Posterior, resid, fixed_effects,
	                genetic_effects, Factors, interaction_effects)
	        end
	    end
	end


text:
function kooshballGA(Nr, Ncyc, Nt; thetaRot = 0, phiRot = 0, delay = (0, 0, 0), T = Float32)
    gm1, gm2 = calculateGoldenMeans()
    theta = acos.(mod.((0:(Ncyc*Nt-1)) * gm1, 1))
    phi = (0:(Ncyc*Nt-1)) * 2π * gm2

    theta = reshape(theta, Nt, Ncyc)
    phi = reshape(phi, Nt, Ncyc)

    return kooshball(Nr, theta', phi'; thetaRot = thetaRot, phiRot = thetaRot, delay = delay, T = T)
end

# delay is in (HF, AP, LR)
function kooshball(Nr, theta, phi; thetaRot = 0, phiRot = 0, delay = (0, 0, 0), T = Float32)
    Ncyc, Nt = size(theta)

    kr = collect(((-Nr+1)/2:(Nr-1)/2) / Nr)
    stheta = sin.(theta)
    ctheta = cos.(theta)
    sphi = sin.(phi)
    cphi = cos.(phi)

    k = Vector{Matrix{T}}(undef, Nt)
    if thetaRot == 0 && phiRot == 0
        for it ∈ eachindex(k)
            ki = Array{T,3}(undef, 3, Nr, Ncyc)
            @batch for ic = 1:Ncyc, ir ∈ 1:Nr
                ki[1, ir, ic] = -stheta[ic, it] * cphi[ic, it] * (kr[ir] + delay[1])
                ki[2, ir, ic] =  stheta[ic, it] * sphi[ic, it] * (kr[ir] + delay[2])
                ki[3, ir, ic] =  ctheta[ic, it]                * (kr[ir] + delay[3])
            end
            k[it] = reshape(ki, 3, :)
            @. k[it] = max(min(k[it], 0.5), -0.5) # avoid NFFT.jl to throw erros. This should alter only very few points
        end
    else
        @info "check"
        sthetaRot = sin(thetaRot)
        cthetaRot = cos(thetaRot)
        sphiRot   = sin(phiRot)
        cphiRot   = cos(phiRot)

        k = Vector{Matrix{T}}(undef, Nt)
        for it ∈ eachindex(k)
            ki = Array{T,3}(undef, 3, Nr, Ncyc)
            @batch for ic = 1:Ncyc, ir ∈ 1:Nr
                ki[1, ir, ic] = -(cphiRot * cphi[ic, it] * cthetaRot * stheta[ic, it] - sphiRot *  sphi[ic, it] * stheta[ic, it] + cphiRot * ctheta[ic, it] * sthetaRot)    * (kr[ir] + delay[1])
                ki[2, ir, ic] =  (cphiRot * sphi[ic, it]             * stheta[ic, it] + sphiRot * (cphi[ic, it] * cthetaRot * stheta[ic, it] + ctheta[ic, it] * sthetaRot)) * (kr[ir] + delay[2])
                ki[3, ir, ic] =  (cthetaRot * ctheta[ic, it] - sthetaRot * cphi[ic, it] * stheta[ic, it])                                                                   * (kr[ir] + delay[3])
            end
            k[it] = reshape(ki, 3, :)
            @. k[it] = max(min(k[it], 0.5), -0.5) # avoid NFFT.jl to throw erros. This should alter only very few points
        end
    end
    return k
end

function calculateGoldenMeans()
    M = [0 1 0; 0 0 1; 1 0 1]
    v = eigvecs(M)
    gm1 = real(v[1, 3] / v[3, 3])
    gm2 = real(v[2, 3] / v[3, 3])
    return gm1, gm2
end


text:
function isvalid(n, rules)
	ok = false
	for cat in rules
		for r in cat
			if n >= r[1] && n <= r[2]
				ok = true
			end
		end
	end
	return ok
end

function isvalid_i(n, rule)
	ok = false
	for r in rule
		if n >= r[1] && n <= r[2]
			ok = true
		end
	end
	return ok
end

function buildrules(f)
	rules = []
	for i=1:20
		l=readline(f)
		push!(rules, [])
		for w in split(l, " ")
			if length(split(w, "-")) == 2
				rule1 = split(w, "-")[1]
				rule2 = split(w, "-")[2]
				rule = [parse(Int64, rule1), parse(Int64, rule2)]
				push!(rules[i], rule)
			end
		end
	end
	(f, rules)
end

# returns solution of part 1
function x()
	f = open("16.txt")
	(f, rules) = buildrules(f)

	for i=1:5
		readline(f)
	end

	s = 0
	for i=1:244
		l=readline(f)
		ok = true
		for n in split(l, ",")
			if !isvalid(parse(Int64, n), rules)
				s += parse(Int64, n)
			end
		end
	end
	s
end

# returns solution of part 2
function y()
	f = open("16.txt")
	(f, rules) = buildrules(f)
	readline(f)
	readline(f)
	ticket = [parse(Int64,t) for t in split(readline(f), ",")]
	readline(f)
	readline(f)

	tab = Array{Int64,2}(undef, 244, 20)
	k = 1
	for i=1:244
		l=readline(f)
		t = split(l, ",")
		for j=1:20
			if !isvalid(parse(Int64,t[j]), rules)
				@goto here
			end
			tab[k,j] = parse(Int64,t[j])
		end
		k += 1
		@label here
	end
	k -= 1
	table = Array{Int64,2}(undef, k, 20)
	for i=1:k, j=1:20
		table[i,j] = tab[i,j]
	end

	a = []
	for i=1:20
		s = Set(collect(1:20))
		for j=1:k
			s2 = Set()
			for r = 1:20
				if isvalid_i(table[j,i], rules[r])
					push!(s2, r)
				end
			end
			intersect!(s, s2)
		end
		push!(a, s)
	end

	removed = Set{Int64}()
	for q=1:19
		el = 0
		for i=1:20
			if length(a[i]) == 1 && !in(first(a[i]), removed)
				el = first(a[i])
				push!(removed, el)
				break
			end
		end
		for b in a
			if length(b) > 1
				delete!(b, el)
			end
		end
	end
	res = 1
	for i=1:20
		if any(in.([1,2,3,4,5,6], repeat([a[i]],6)))
			res *= ticket[i]
		end
	end
	res
end


text:
using Mocking

cancel_rotate_secret_1_patch = @patch function cancel_rotate_secret(a...; b...)
    return Dict{String, Any}("Name" => "Name", "ARN" => "arn:aws:secretsmanager:us-west-2:123456789012:secret:MyTestDatabaseSecret-a1b2c3")
end

create_secret_1_patch = @patch function create_secret(a...; b...)
    return Dict{String, Any}("VersionId" => "EXAMPLE1-90ab-cdef-fedc-ba987SECRET1", "Name" => "MyTestDatabaseSecret", "ARN" => "arn:aws:secretsmanager:us-west-2:123456789012:secret:MyTestDatabaseSecret-a1b2c3")
end

delete_resource_policy_1_patch = @patch function delete_resource_policy(a...; b...)
    return Dict{String, Any}("Name" => "MyTestDatabaseSecret", "ARN" => "arn:aws:secretsmanager:us-west-2:123456789012:secret:MyTestDatabaseMasterSecret-a1b2c3")
end

delete_secret_1_patch = @patch function delete_secret(a...; b...)
    return Dict{String, Any}("Name" => "MyTestDatabaseSecret", "ARN" => "arn:aws:secretsmanager:us-west-2:123456789012:secret:MyTestDatabaseSecret-a1b2c3", "DeletionDate" => "1524085349.095")
end

describe_secret_1_patch = @patch function describe_secret(a...; b...)
    return Dict{String, Any}("RotationLambdaARN" => "arn:aws:lambda:us-west-2:123456789012:function:MyTestRotationLambda", "RotationEnabled" => true, "ARN" => "arn:aws:secretsmanager:us-west-2:123456789012:secret:MyTestDatabaseSecret-a1b2c3", "LastChangedDate" => 1.523477145729e9, "LastAccessedDate" => "1523923200", "Tags" => Any[Dict{String, Any}("Value" => "AnotherValue", "Key" => "SecondTag"), Dict{String, Any}("Value" => "SomeValue", "Key" => "FirstTag")], "Name" => "MyTestDatabaseSecret", "VersionIdsToStages" => Dict{String, Any}("EXAMPLE2-90ab-cdef-fedc-ba987EXAMPLE" => Any["AWSCURRENT"], "EXAMPLE1-90ab-cdef-fedc-ba987EXAMPLE" => Any["AWSPREVIOUS"]), "Description" => "My test database secret", "LastRotatedDate" => 1.52574725372e9, "KmsKeyId" => "arn:aws:kms:us-west-2:123456789012:key/EXAMPLE1-90ab-cdef-fedc-ba987KMSKEY1", "RotationRules" => Dict{String, Any}("AutomaticallyAfterDays" => 30))
end

get_random_password_1_patch = @patch function get_random_password(a...; b...)
    return Dict{String, Any}("RandomPassword" => "N+Z43a,>vx7j O8^*<8i3")
end

get_resource_policy_1_patch = @patch function get_resource_policy(a...; b...)
    return Dict{String, Any}("ResourcePolicy" => "{\n\"Version\":\"2012-10-17\",\n\"Statement\":[{\n\"Effect\":\"Allow\",\n\"Principal\":{\n\"AWS\":\"arn:aws:iam::123456789012:root\"\n},\n\"Action\":\"secretsmanager:GetSecretValue\",\n\"Resource\":\"*\"\n}]\n}", "Name" => "MyTestDatabaseSecret", "ARN" => "arn:aws:secretsmanager:us-west-2:123456789012:secret:MyTestDatabaseSecret-a1b2c3")
end

get_secret_value_1_patch = @patch function get_secret_value(a...; b...)
    return Dict{String, Any}("SecretString" => "{\n  \"username\":\"david\",\n  \"password\":\"BnQw&XDWgaEeT9XGTT29\"\n}\n", "CreatedDate" => 1.523477145713e9, "VersionStages" => Any["AWSPREVIOUS"], "VersionId" => "EXAMPLE1-90ab-cdef-fedc-ba987SECRET1", "Name" => "MyTestDatabaseSecret", "ARN" => "arn:aws:secretsmanager:us-west-2:123456789012:secret:MyTestDatabaseSecret-a1b2c3")
end

list_secret_version_ids_1_patch = @patch function list_secret_version_ids(a...; b...)
    return Dict{String, Any}("Versions" => Any[Dict{String, Any}("CreatedDate" => 1.523477145713e9, "VersionStages" => Any["AWSPREVIOUS"], "VersionId" => "EXAMPLE1-90ab-cdef-fedc-ba987EXAMPLE"), Dict{String, Any}("CreatedDate" => 1.523486221391e9, "VersionStages" => Any["AWSCURRENT"], "VersionId" => "EXAMPLE2-90ab-cdef-fedc-ba987EXAMPLE"), Dict{String, Any}("CreatedDate" => 1.51197446236e9, "VersionId" => "EXAMPLE3-90ab-cdef-fedc-ba987EXAMPLE;")], "Name" => "MyTestDatabaseSecret", "ARN" => "arn:aws:secretsmanager:us-west-2:123456789012:secret:MyTestDatabaseSecret-a1b2c3")
end

list_secrets_1_patch = @patch function list_secrets(a...; b...)
    return Dict{String, Any}("SecretList" => Any[Dict{String, Any}("Description" => "My test database secret", "SecretVersionsToStages" => Dict{String, Any}("EXAMPLE1-90ab-cdef-fedc-ba987EXAMPLE" => Any["AWSCURRENT"]), "Name" => "MyTestDatabaseSecret", "ARN" => "arn:aws:secretsmanager:us-west-2:123456789012:secret:MyTestDatabaseSecret-a1b2c3", "LastChangedDate" => 1.523477145729e9), Dict{String, Any}("Description" => "Another secret created for a different database", "SecretVersionsToStages" => Dict{String, Any}("EXAMPLE2-90ab-cdef-fedc-ba987EXAMPLE" => Any["AWSCURRENT"]), "Name" => "MyTestDatabaseSecret1", "ARN" => "arn:aws:secretsmanager:us-west-2:123456789012:secret:MyTestDatabaseSecret1-d4e5f6", "LastChangedDate" => 1.523482025685e9)])
end

put_resource_policy_1_patch = @patch function put_resource_policy(a...; b...)
    return Dict{String, Any}("Name" => "MyTestDatabaseSecret", "ARN" => "arn:aws:secretsmanager:us-west-2:123456789012:secret:MyTestDatabaseSecret-a1b2c3")
end

put_secret_value_1_patch = @patch function put_secret_value(a...; b...)
    return Dict{String, Any}("VersionStages" => Any["AWSCURRENT"], "VersionId" => "EXAMPLE2-90ab-cdef-fedc-ba987EXAMPLE", "Name" => "MyTestDatabaseSecret", "ARN" => "arn:aws:secretsmanager:us-west-2:123456789012:secret:MyTestDatabaseSecret-a1b2c3")
end

restore_secret_1_patch = @patch function restore_secret(a...; b...)
    return Dict{String, Any}("Name" => "MyTestDatabaseSecret", "ARN" => "arn:aws:secretsmanager:us-west-2:123456789012:secret:MyTestDatabaseSecret-a1b2c3")
end

rotate_secret_1_patch = @patch function rotate_secret(a...; b...)
    return Dict{String, Any}("VersionId" => "EXAMPLE2-90ab-cdef-fedc-ba987SECRET2", "Name" => "MyTestDatabaseSecret", "ARN" => "arn:aws:secretsmanager:us-west-2:123456789012:secret:MyTestDatabaseSecret-a1b2c3")
end

rotate_secret_2_patch = @patch function rotate_secret(a...; b...)
    return Dict{String, Any}("SecretARN" => "arn:aws:secretsmanager:us-west-2:123456789012:secret:MyTestDatabaseSecret-a1b2c3", "SecretName" => "MyTestDatabaseSecret", "SecretVersionId" => "EXAMPLE2-90ab-cdef-fedc-ba987SECRET2")
end

update_secret_1_patch = @patch function update_secret(a...; b...)
    return Dict{String, Any}("Name" => "MyTestDatabaseSecret", "ARN" => "arn:aws:secretsmanager:us-west-2:123456789012:secret:MyTestDatabaseSecret-a1b2c3")
end

update_secret_2_patch = @patch function update_secret(a...; b...)
    return Dict{String, Any}("Name" => "MyTestDatabaseSecret", "ARN" => "arn:aws:secretsmanager:us-west-2:123456789012:secret:MyTestDatabaseSecret-a1b2c3")
end

update_secret_3_patch = @patch function update_secret(a...; b...)
    return Dict{String, Any}("VersionId" => "EXAMPLE1-90ab-cdef-fedc-ba987EXAMPLE", "Name" => "MyTestDatabaseSecret", "ARN" => "aws:arn:secretsmanager:us-west-2:123456789012:secret:MyTestDatabaseSecret-a1b2c3")
end

update_secret_version_stage_1_patch = @patch function update_secret_version_stage(a...; b...)
    return Dict{String, Any}("Name" => "MyTestDatabaseSecret", "ARN" => "arn:aws:secretsmanager:us-west-2:123456789012:secret:MyTestDatabaseSecret-a1b2c3")
end

update_secret_version_stage_2_patch = @patch function update_secret_version_stage(a...; b...)
    return Dict{String, Any}("Name" => "MyTestDatabaseSecret", "ARN" => "arn:aws:secretsmanager:us-west-2:123456789012:secret:MyTestDatabaseSecret-a1b2c3")
end

update_secret_version_stage_3_patch = @patch function update_secret_version_stage(a...; b...)
    return Dict{String, Any}("Name" => "MyTestDatabaseSecret", "ARN" => "arn:aws:secretsmanager:us-west-2:123456789012:secret:MyTestDatabaseSecret-a1b2c3")
end

validate_resource_policy_1_patch = @patch function validate_resource_policy(a...; b...)
    return Dict{String, Any}("PolicyValidationPassed" => true, "ValidationErrors" => Any[])
end


text:
module Methods
export MethodParams

using FactorizationMachines: FMMatrix, FMFloat, FMInt
using FactorizationMachines.Tasks: PredictorTask, loss_deriv
using FactorizationMachines.Models: FMModel
using FactorizationMachines.Predictors: FMPredictor, predict_instance!
using FactorizationMachines.Evaluators: Evaluator, evaluate!

abstract MethodParams

immutable SGDMethod <: MethodParams
  alpha::FMFloat
  num_epochs::Int

  # regularization
  reg0::FMFloat
  regw::FMFloat
  regv::FMFloat

  SGDMethod(; alpha::FMFloat = 0.01, num_epochs::Int = 100,
              reg0::FMFloat = .0, regw::FMFloat = .0, regv::FMFloat = .0) = new(alpha, num_epochs, reg0, regw, regv)
end
const sgd = SGDMethod

function sgd_train!{T<:PredictorTask}(
    sgd::SGDMethod, evaluator::Evaluator, predictor::FMPredictor{T},
    X::FMMatrix, y::StridedVector{FMFloat})

    predictions = zeros(length(y))
    f_sum = zeros(predictor.model.num_factors)
    sum_sqr = zeros(predictor.model.num_factors)

    info("Learning Factorization Machines with gradient descent...")
    for epoch in 1:sgd.num_epochs
        #info("[SGD - Epoch $epoch] Start...")
        @time sgd_epoch!(sgd, evaluator, predictor,
                         X, y, epoch, sgd.alpha,
                         predictions, f_sum, sum_sqr)
        #info("[SGD - Epoch $epoch] End.")
    end
end

function sgd_epoch!{T<:PredictorTask}(
        sgd::SGDMethod, evaluator::Evaluator, predictor::FMPredictor{T},
        X::FMMatrix, y::StridedVector{FMFloat}, epoch::Integer, alpha::FMFloat,
        predictions::Vector{FMFloat}, f_sum::Vector{FMFloat}, sum_sqr::Vector{FMFloat})

    p = zero(FMFloat)
    mult = zero(FMFloat)

    for c in 1:X.n
        X_nzrange = nzrange(X, c)
        idx = sub(X.rowval, X_nzrange)
        x = sub(X.nzval, X_nzrange)
        #info("DEBUG: processing $c")
        p = predict_instance!(predictor, idx, x, f_sum, sum_sqr)
        #info("DEBUG: prediction - p: $p, f_sum: $f_sum, sum_sqr: $sum_sqr")
        mult = loss_deriv(predictor.task, p, y[c])
        #info("DEBUG: mult: $mult")
        sgd_update!(sgd, predictor.model, alpha, idx, x, mult, f_sum)
    end
    #evaluation
    @time evaluation = evaluate!(evaluator, predictor, X, y, predictions)
    info("[SGD - Epoch $epoch] Evaluation: $evaluation")
end

function sgd_update!(
        sgd::SGDMethod, model::FMModel, alpha::FMFloat,
        idx::StridedVector{Int64}, x::StridedVector{FMFloat},
        mult::FMFloat, f_sum::Vector{FMFloat})

    if model.k0
        model.w0 -= alpha * (mult + sgd.reg0 * model.w0)
    end
    if model.k1
       for i in 1:length(idx)
            model.w[idx[i]] -= alpha * (mult * x[i] + sgd.regw * model.w[idx[i]])
        end
    end
    for f in 1:model.num_factors
       for i in 1:length(idx)
            grad = f_sum[f] * x[i] - model.V[f,idx[i]] * x[i] * x[i]
            model.V[f,idx[i]] -= alpha * (mult * grad + sgd.regv * model.V[f,idx[i]])
        end
    end
end

end


text:
"""
	Proxy(proxyType::AbstractString;
          proxyAutoconfigUrl::Union{Nothing, AbstractString} = nothing,
          ftpProxy::Union{Nothing, AbstractString} = nothing,
          httpProxy::Union{Nothing, AbstractString} = nothing,
          noProxy::Union{Nothing, AbstractVector{<:AbstractString}} = nothing,
          sslProxy::Union{Nothing, AbstractString} = nothing,
          socksProxy::Union{Nothing, AbstractString} = nothing,
          socksVersion::Union{Nothing, Integer} = nothing)::Proxy

The proxy configuration capability is a JSON Object nested within the primary capabilities.
According to the [W3C](https://www.w3.org/TR/webdriver/#proxy).
"""
struct Proxy{
    pAU<:Union{Nothing,AbstractString},
    ftpP<:Union{Nothing,AbstractString},
    httpP<:Union{Nothing,AbstractString},
    nP<:Union{Nothing,AbstractVector{<:AbstractString}},
    sslP<:Union{Nothing,AbstractString},
    sP<:Union{Nothing,AbstractString},
    sV<:Union{Nothing,Integer},
}
    proxyType::String
    proxyAutoconfigUrl::pAU
    ftpProxy::ftpP
    httpProxy::httpP
    noProxy::nP
    sslProxy::sslP
    socksProxy::sP
    socksVersion::sV
    function Proxy(
        proxyType::AbstractString;
        proxyAutoconfigUrl::Union{Nothing,AbstractString} = nothing,
        ftpProxy::Union{Nothing,AbstractString} = nothing,
        httpProxy::Union{Nothing,AbstractString} = nothing,
        noProxy::Union{Nothing,AbstractVector{<:AbstractString}} = nothing,
        sslProxy::Union{Nothing,AbstractString} = nothing,
        socksProxy::Union{Nothing,AbstractString} = nothing,
        socksVersion::Union{Nothing,Integer} = nothing,
    )::Proxy
        proxyType ∈ ["pac", "direct", "autodetect", "system", "manual"] ||
        throw(ArgumentError("""valid proxyType values: "pac", "direct", "autodetect", "system", or "manual"."""))
        proxyType == "pac" &&
        isnothing(proxyAutoconfigUrl) &&
        throw(ArgumentError("proxyAutoconfigUrl must be provided for proxyType pac"))
        if !isnothing(socksProxy)
            isnothing(socksVersion) &&
            throw(ArgumentError("socksVersion must be provided for socksProxy"))
            0 ≤ socksVersion ≤ 255 ||
            throw(ArgumentError("valid values for socksVersion: any integer between 0 and 255 inclusive."))
        end
        new{
            typeof(proxyAutoconfigUrl),
            typeof(ftpProxy),
            typeof(httpProxy),
            typeof(noProxy),
            typeof(sslProxy),
            typeof(socksProxy),
            typeof(socksVersion),
        }(
            proxyType,
            proxyAutoconfigUrl,
            ftpProxy,
            httpProxy,
            noProxy,
            sslProxy,
            socksProxy,
            socksVersion,
        )
    end
end
summary(io::IO, obj::Proxy) = println(io, "Proxy")
function show(io::IO, obj::Proxy)
    print(io, summary(obj))
end


text:
# using Test

# Primary @testset

# Error reporting.
println("="^50)
@info("The following errors are expected output.")
# include(joinpath("errors", "make.jl"))
@info("END of expected error output.")
println("="^50)


text:
@deprecate visPointCloudOnPose!(args...;kwargs...) visPointCloud!(args...;kwargs...)

"""
    $(SIGNATURES)
Draw point cloud on [vis].
xTc -> object(vis) to camera transform, # Use material to set size of particles or other propeties
"""
function visPointCloud!(vis::Visualizer, pointcloud::PointCloud; xTc::SE3 = SE3([0,0,0],I), material = PointsMaterial(size=0.005) )::Nothing
	setobject!(vis, pointcloud, material)
	trans = Translation(xTc.t[1], xTc.t[2], xTc.t[3])∘LinearMap(UnitQuaternion(xTc.R.R))
	settransform!(vis, trans)
	return nothing
end

max_stars_repo_name: Affie/Amphitheatre

max_issues_repo_name: Affie/Amphitheatre


text:
#=
Enable or display display for particular channel in multi-channel display
=#

popup_enable_cb(w::Ptr,d::Tuple{Gui_Handles,RHD2000})=enable_disable(d[1],true,d[2].save.backup)

popup_disable_cb(w::Ptr,d::Tuple{Gui_Handles,RHD2000})=enable_disable(d[1],false,d[2].save.backup)

function enable_disable(han::Gui_Handles,en::Bool,backup)

    if han.c_right_top==1 #16 channel
        (inmulti,count)=check_multi(han,4,4,16,han.mim[1],han.mim[2])
    elseif han.c_right_top==2 # 32 channel
        (inmulti,count)=check_multi(han,6,6,32,han.mim[1],han.mim[2])
    else #64 channel
        (inmulti,count)=check_multi(han,11,6,64,han.mim[1],han.mim[2])
    end

    if inmulti
        han.enabled[han.chan_per_display*han.num16-han.chan_per_display+count]=en
        f=open(string(backup,"enabled.bin"),"w")
        write(f,han.enabled)
        close(f)
    end

    nothing
end

#=
Plotting multi channel spike display
=#

draw_spike16(rhd::RHD2000,han::Gui_Handles)=draw_spike_n(rhd,han,4,4,16)

draw_spike32(rhd::RHD2000,han::Gui_Handles)=draw_spike_n(rhd,han,6,6,32)

draw_spike64(rhd::RHD2000,han::Gui_Handles)=draw_spike_n(rhd,han,6,11,64)

function draw_spike_n(rhd::RHD2000,han::Gui_Handles,n_col,n_row,num_chan)

    k_in=num_chan*(han.num16)-num_chan+1

    if (k_in+num_chan-1)>size(rhd.v,2)
        num_chan=(size(rhd.v,2)-k_in+1)
    end

    num_plot =n_col*n_row

    maxid=find_max_id(rhd,han,k_in,num_chan)
    ctx=Gtk.getgc(han.c)
    xwidth=width(ctx)
    myheight=height(ctx)
    if num_plot<64
      yheight=myheight-300
    else
      yheight=myheight
    end

    Cairo.scale(ctx,xwidth/(han.wave_points/2*n_col),1)

    #subsequent IDs
    @inbounds for thisid=1:maxid
	for chan=k_in:(k_in+num_chan-1)
	    if han.enabled[chan]
	        for g=1:rhd.nums[chan]
                    if (rhd.buf[g,chan].inds.start>0)&(rhd.buf[g,chan].inds.stop<size(rhd.v,1))
                        if rhd.buf[g,chan].id==thisid

                            #Gain and offset for channel
                            s=han.scale[chan,2]
                            o=han.offset[chan]

                            #x and y position for channel location
			    startx=div(rem(chan-1,num_plot),n_row)*han.wave_points/2+1
			    starty=yheight/n_row*(rem(rem(chan-1,num_plot),n_row))+yheight/n_row/2

                            #Max and min extents for line to stay within bounding box
                            ymax=starty+yheight/n_row/2
			    ymin=starty-yheight/n_row/2

                            y=(rhd.v[rhd.buf[g,chan].inds.start,chan]-o)*s+starty

			    if (y<ymin)
                               y=ymin
                            elseif (y>ymax)
                               y=ymax
                            end

                            move_to(ctx,startx,y)
                            for kk=rhd.buf[g,chan].inds.start+2:2:rhd.buf[g,chan].inds.stop
                                y=(rhd.v[kk,chan]-o)*s+starty
                                if (y<ymin)
                                   y=ymin
                                elseif (y>ymax)
                                   y=ymax
                                end
                                line_to(ctx,startx,y)
                                startx+=1
                            end
                        end
                    end
                end
	    end
            if chan>length(han.enabled)
                break
            end
	end
	set_line_width(ctx,0.25);
        @inbounds select_color(ctx,thisid)
        stroke(ctx)
    end

    identity_matrix(ctx)
    nothing
end

function find_max_id(rhd::RHD2000,han::Gui_Handles,k,num)

    maxid=1

    for i=k:(k+num-1)
        if han.enabled[i]
            for g=1:rhd.nums[i]
                if rhd.buf[g,i].id>maxid
                    maxid=rhd.buf[g,i].id
                end
            end
        end
    end
    maxid
end

#=
Highlight selected channel
=#

function highlight_channel(han::Gui_Handles,old_spike)

    ctx = Gtk.getgc(han.c)

    if han.c_right_top==1

        (x1_i,x2_i,y1_i,y2_i)=get_multi_dims(han,4,4,16,old_spike)
        (x1_f,x2_f,y1_f,y2_f)=get_multi_dims(han,4,4,16,han.num)

    elseif han.c_right_top==2

        (x1_i,x2_i,y1_i,y2_i)=get_multi_dims(han,6,6,32,old_spike)
        (x1_f,x2_f,y1_f,y2_f)=get_multi_dims(han,6,6,32,han.num)

    elseif han.c_right_top==3
        (x1_i,x2_i,y1_i,y2_i)=get_multi_dims(han,6,11,64,old_spike)
        (x1_f,x2_f,y1_f,y2_f)=get_multi_dims(han,6,11,64,han.num)
    end

    if han.c_right_top<4
        draw_box(x1_i,y1_i,x2_i,y2_i,(0.0,0.0,0.0),2.0,ctx)
        draw_box(x1_i,y1_i,x2_i,y2_i,(1.0,1.0,1.0),1.0,ctx)
        draw_box(x1_f,y1_f,x2_f,y2_f,(1.0,0.0,1.0),1.0,ctx)
    end

    nothing
end

#=
Prepare multi channel display
=#

function draw_multi_chan(ctx::Cairo.CairoContext,han::Gui_Handles,k,n_row,n_col,chan_num)

    mywidth=width(ctx)

    if chan_num<64
        myheight=height(ctx)-300.0
    else
        myheight=height(ctx)
    end

    xbounds=get_bounds(mywidth,n_col+1)
    ybounds=get_bounds(myheight,n_row+1)

    for x in xbounds
        line(ctx,x,x,1,myheight)
    end
    for y in ybounds
        line(ctx,1,mywidth,y,y)
    end
    set_source_rgb(ctx,1.0,1.0,1.0)
    set_line_width(ctx,1.0)
    stroke(ctx)

    for x=1:n_col
        for y=1:n_row
            if k<=length(han.enabled)
                move_to(ctx,xbounds[x]+10.0,ybounds[y]+10.0)
                if han.enabled[k]
                    show_text(ctx,string(k))
                else
                    show_text(ctx,string(k,"-DISABLED"))
                end
            end
            k+=1
        end
    end
    (x1_f,x2_f,y1_f,y2_f)=get_multi_dims(han,n_col,n_row,chan_num,han.num)
    draw_box(x1_f,y1_f,x2_f,y2_f,(1.0,0.0,1.0),1.0,ctx)
    nothing
end

prepare_16(ctx::Cairo.CairoContext,han::Gui_Handles)=draw_multi_chan(ctx,han,16*han.num16-15,4,4,16)

prepare_32(ctx::Cairo.CairoContext,han::Gui_Handles)=draw_multi_chan(ctx,han,32*han.num16-31,6,6,32)

prepare_64(ctx::Cairo.CairoContext,han::Gui_Handles)=draw_multi_chan(ctx,han,64*han.num16-63,11,6,64)


text:
module SimpleProbabilitySets

using Distributions
using RCall

"""
    SimpleProbabilitySet

Abstract type for representing sets of probability distributions.
"""
abstract type SimpleProbabilitySet end

include("pbox.jl")
export
    PBox,
    pdfs,
    cdfs,
    pints

include("pinterval.jl")
export
    PInterval,
    psample

end


text:
# Identity

"""
    tr_identity(i, x)
    tr_identity(x)
    tr_identity(x, X::AbstractVector)

Identity function. Already defined in Julia as `identity`, specialized for vectors.
When `X` is provided, the result is computed without allocations.
"""
tr_identity(i, x) = identity(x[i])
lazy(tr_identity)

# Count equalities

"""
    tr_count_eq(i, x)
    tr_count_eq(x)
    tr_count_eq(x, X::AbstractVector)

Count the number of elements equal to `x[i]`. Extended method to vector with sig `(x)` are generated.
When `X` is provided, the result is computed without allocations.
"""
tr_count_eq(i, x) = count(y -> x[i] == y, x) - 1

"""
    tr_count_eq_right(i, x)
    tr_count_eq_right(x)
    tr_count_eq_right(x, X::AbstractVector)

Count the number of elements to the right of and equal to `x[i]`. Extended method to vector with sig `(x)` are generated.
When `X` is provided, the result is computed without allocations.
"""
tr_count_eq_right(i, x) = tr_count_eq(1, @view x[i:end])

"""
    tr_count_eq_left(i, x)
    tr_count_eq_left(x)
    tr_count_eq_left(x, X::AbstractVector)

Count the number of elements to the left of and equal to `x[i]`. Extended method to vector with sig `(x)` are generated.
When `X` is provided, the result is computed without allocations.
"""
tr_count_eq_left(i, x) = tr_count_eq(i, @view x[1:i])

# Generating vetorized versions
lazy(tr_count_eq, tr_count_eq_left, tr_count_eq_right)

# Count greater/lesser

"""
    tr_count_greater(i, x)
    tr_count_greater(x)
    tr_count_greater(x, X::AbstractVector)

Count the number of elements greater than `x[i]`. Extended method to vector with sig `(x)` are generated.
When `X` is provided, the result is computed without allocations.
"""
tr_count_greater(i, x) = count(y -> x[i] < y, x)

"""
    tr_count_lesser(i, x)
    tr_count_lesser(x)
    tr_count_lesser(x, X::AbstractVector)

Count the number of elements lesser than `x[i]`. Extended method to vector with sig `(x)` are generated.
When `X` is provided, the result is computed without allocations.
"""
tr_count_lesser(i, x) = count(y -> x[i] > y, x)

"""
    tr_count_g_left(i, x)
    tr_count_g_left(x)
    tr_count_g_left(x, X::AbstractVector)

Count the number of elements to the left of and greater than `x[i]`. Extended method to vector with sig `(x)` are generated.
When `X` is provided, the result is computed without allocations.
"""
tr_count_g_left(i, x) = tr_count_greater(i, @view x[1:i])

"""
    tr_count_l_left(i, x)
    tr_count_l_left(x)
    tr_count_l_left(x, X::AbstractVector)

Count the number of elements to the left of and lesser than `x[i]`. Extended method to vector with sig `(x)` are generated.
When `X` is provided, the result is computed without allocations.
"""
tr_count_l_left(i, x) = tr_count_lesser(i, @view x[1:i])

"""
    tr_count_g_right(i, x)
    tr_count_g_right(x)
    tr_count_g_right(x, X::AbstractVector)

Count the number of elements to the right of and greater than `x[i]`. Extended method to vector with sig `(x)` are generated.
"""
tr_count_g_right(i, x) = tr_count_greater(1, @view x[i:end])

"""
    tr_count_l_right(i, x)
    tr_count_l_right(x)
    tr_count_l_right(x, X::AbstractVector)

Count the number of elements to the right of and lesser than `x[i]`. Extended method to vector with sig `(x)` are generated.
When `X` is provided, the result is computed without allocations.
"""
tr_count_l_right(i, x) = tr_count_lesser(1, @view x[i:end])

# Generating vetorized versions
lazy(tr_count_greater, tr_count_g_left, tr_count_g_right)
lazy(tr_count_lesser, tr_count_l_left, tr_count_l_right)

# Count param

"""
    tr_count_eq_param(i, x; param)
    tr_count_eq_param(x; param)
    tr_count_eq_param(x, X::AbstractVector; param)

Count the number of elements equal to `x[i] + param`. Extended method to vector with sig `(x, param)` are generated.
When `X` is provided, the result is computed without allocations.
"""
tr_count_eq_param(i, x; param) = count(y -> y == x[i] + param, x)

"""
    tr_count_l_param(i, x; param)
    tr_count_l_param(x; param)
    tr_count_l_param(x, X::AbstractVector; param)

Count the number of elements lesser than `x[i] + param`. Extended method to vector with sig `(x, param)` are generated.
When `X` is provided, the result is computed without allocations.
"""
tr_count_l_param(i, x; param) = count(y -> y < x[i] + param, x)

"""
    tr_count_g_param(i, x; param)
    tr_count_g_param(x; param)
    tr_count_g_param(x, X::AbstractVector; param)

Count the number of elements greater than `x[i] + param`. Extended method to vector with sig `(x, param)` are generated.
When `X` is provided, the result is computed without allocations.
"""
tr_count_g_param(i, x; param) = count(y -> y > x[i] + param, x)

# Generating vetorized versions
lazy_param(tr_count_eq_param, tr_count_l_param, tr_count_g_param)

# Bounding param

"""
    tr_count_bounding_param(i, x; param)
    tr_count_bounding_param(x; param)
    tr_count_bounding_param(x, X::AbstractVector; param)

Count the number of elements bounded (not strictly) by `x[i]` and `x[i] + param`. An extended method to vector with sig `(x, param)` is generated.
When `X` is provided, the result is computed without allocations.
"""
tr_count_bounding_param(i, x; param) = count(y -> x[i] ≤ y ≤ x[i] + param, x)

# Generating vetorized versions
lazy_param(tr_count_bounding_param)

# Val/param substractions

"""
    tr_val_minus_param(i, x; param)
    tr_val_minus_param(x; param)
    tr_val_minus_param(x, X::AbstractVector; param)

Return the difference `x[i] - param` if positive, `0.0` otherwise.  Extended method to vector with sig `(x, param)` are generated.
When `X` is provided, the result is computed without allocations.
"""
tr_val_minus_param(i, x; param) = max(0, x[i] - param)

"""
    tr_param_minus_val(i, x; param)
    tr_param_minus_val(x; param)
    tr_param_minus_val(x, X::AbstractVector; param)

Return the difference `param - x[i]` if positive, `0.0` otherwise.  Extended method to vector with sig `(x, param)` are generated.
When `X` is provided, the result is computed without allocations.
"""
tr_param_minus_val(i, x; param) = max(0, param - x[i])

# Generating vetorized versions
lazy_param(tr_val_minus_param, tr_param_minus_val)

# Continuous values substraction
"""
    tr_contiguous_vals_minus(i, x)
    tr_contiguous_vals_minus(x)
    tr_contiguous_vals_minus(x, X::AbstractVector)

Return the difference `x[i] - x[i + 1]` if positive, `0.0` otherwise. Extended method to vector with sig `(x)` are generated.
When `X` is provided, the result is computed without allocations.
"""
tr_contiguous_vals_minus(i, x; param=nothing) = length(x) == i ? 0 : tr_val_minus_param(i, x; param=x[i + 1])

"""
    tr_contiguous_vals_minus_rev(i, x)
    tr_contiguous_vals_minus_rev(x)
    tr_contiguous_vals_minus_rev(x, X::AbstractVector)

Return the difference `x[i + 1] - x[i]` if positive, `0.0` otherwise. Extended method to vector with sig `(x)` are generated.
When `X` is provided, the result is computed without allocations.
"""
function tr_contiguous_vals_minus_rev(i, x; param=nothing)
    return length(x) == i ? 0 : tr_param_minus_val(i, x; param=x[i + 1])
end

# Generating vetorized versions
lazy(tr_contiguous_vals_minus, tr_contiguous_vals_minus_rev)

"""
    transformation_layer(param = false)
Generate the layer of transformations functions of the ICN. Iff `param` value is true, also includes all the parametric transformations.
"""
function transformation_layer(param=false)
    transformations = LittleDict{Symbol,Function}(
        :identity => tr_identity,
        :count_eq => tr_count_eq,
        :count_eq_left => tr_count_eq_left,
        :count_eq_right => tr_count_eq_right,
        :count_greater => tr_count_greater,
        :count_lesser => tr_count_lesser,
        :count_g_left => tr_count_g_left,
        :count_l_left => tr_count_l_left,
        :count_g_right => tr_count_g_right,
        :count_l_right => tr_count_l_right,
        :contiguous_vals_minus => tr_contiguous_vals_minus,
        :contiguous_vals_minus_rev => tr_contiguous_vals_minus_rev,
    )

    if param
        transformations_param = LittleDict{Symbol,Function}(
            :count_eq_param => tr_count_eq_param,
            :count_l_param => tr_count_l_param,
            :count_g_param => tr_count_g_param,
            :count_bounding_param => tr_count_bounding_param,
            :val_minus_param => tr_val_minus_param,
            :param_minus_val => tr_param_minus_val,
        )
        transformations = LittleDict(union(transformations, transformations_param))
    end

    return Layer(transformations, false)
end


text:
using Debug
@debug_analyze function f(x)
    outer = @localscope
    local inner
    pos = "outer"
    let pos = "inner"
        y = x
        inner = @localscope
    end
    (outer, inner)
end

outer, inner = f(5)

@show keys(outer) keys(inner)

println()
@show outer[:x] inner[:x]     # x is the same variable in both scopes
@show outer[:pos] inner[:pos] # pos refers to different variables in inner and outer

println("\nSetting `inner[:x] = 3`:")
inner[:x] = 3             # assigns to the single x variable
@show outer[:x] inner[:x] # both values have been updated

println()
@show debug_eval(inner, :(x*x)) # evaluate an expression in the inner scope


text:
module MicroMamba

if isdefined(Base, :Experimental) && isdefined(Base.Experimental, Symbol("@compiler_options"))
    # Note: compile=min makes --code-coverage not work
    @eval Base.Experimental.@compiler_options optimize=0 infer=false #compile=min
end

import Pkg.Artifacts: ensure_artifact_installed
import Scratch: @get_scratch!

mutable struct State
    root_dir::String
    available::Bool
    executable::String
    version::VersionNumber
end

const STATE = State("", true, "", VersionNumber(0))

const DEFAULT_VERSION = v"0.24.0"
const ARTIFACTS_TOML = joinpath(dirname(@__DIR__), "Artifacts.toml")
const ARTIFACT_NAME = "micromamba-$(DEFAULT_VERSION)"

"""
    executable()

Return the path to a MicroMamba executable.

Will download and install MicroMamba if required.

May throw an error, for example if your platform is not supported. See `available()`.
"""
function executable(; io::IO=stderr)
    if STATE.executable == ""
        # install from artifact
        STATE.available = false
        install_dir = ensure_artifact_installed(ARTIFACT_NAME, ARTIFACTS_TOML, io=io)
        if Sys.iswindows()
            exe = joinpath(install_dir, "Library", "bin", "micromamba.exe")
        else
            exe = joinpath(install_dir, "bin", "micromamba")
        end
        # check the executable is executable and the right version
        versionstr = read(`$exe --version`, String)
        # @assert occursin("micromamba: $(DEFAULT_VERSION)", versionstr)
        @assert strip(versionstr) == string(DEFAULT_VERSION)
        # update the state
        STATE.executable = exe
        STATE.version = DEFAULT_VERSION
        STATE.available = true
        # Check if an old MicroMamba directory is still there (~/.julia/micromamba)
        for depotdir in DEPOT_PATH
            olddir = joinpath(depotdir, "micromamba")
            isdir(olddir) && @warn "Old MicroMamba directory still exists, it can be deleted: $olddir"
        end
    end
    STATE.executable
end

"""
    version()

The version of MicroMamba at `executable()`.

Will download and install MicroMamba if required.

May throw an error, for example if your platform is not supported. See `available()`.
"""
function version(; io::IO=stderr)
    if STATE.version == VersionNumber(0)
        executable(io=io)
    end
    STATE.version
end

"""
    available()

Return `true` if MicroMamba is available.

If so, `executable()` and `version()` will not throw.

Will download and install MicroMamba if required.
"""
function available(; io::IO=stderr)
    if STATE.available && STATE.executable == ""
        try
            executable(io=io)
        catch
        end
    end
    STATE.available
end

function root_dir()
    if STATE.root_dir == ""
        # if the user already has mamba installed, re-use its root
        STATE.root_dir = get(ENV, "MAMBA_ROOT_PREFIX", "")
        if STATE.root_dir == ""
            STATE.root_dir = @get_scratch!("root")
        end
    end
    STATE.root_dir
end

"""
    cmd([args])

Construct a command which calls MicroMamba, optionally with additional arguments.

By default, the root prefix is a folder in the Julia depot. It can be over-ridden with
the environment variable `MAMBA_ROOT_PREFIX`.
"""
function cmd(; io::IO=stderr)
    exe = executable(io=io)
    root = root_dir()
    `$exe -r $root`
end
cmd(args; io::IO=stderr) = `$(cmd(io=io)) $args`

end # module


text:
# ------------------------------------------------------------------
# Licensed under the MIT License. See LICENSE in the project root.
# ------------------------------------------------------------------

# auxiliary functions and variables
uniform(h; λ)      = (h ≤ λ)
triangular(h; λ)   = (h ≤ λ) * (λ - h)
epanechnikov(h; λ) = (h ≤ λ) * (λ^2 - h^2)
kernfun = Dict(
  :uniform => uniform,
  :triangular => triangular,
  :epanechnikov => epanechnikov
)

"""
    GHC(k, λ; kern=:epanechnikov, link=:ward)

A method for partitioning spatial data into `k` clusters
according to a range `λ` using Geostatistical Hierarchical
Clustering (GHC). The larger the range the more connected
are nearby samples.

## Parameters

* `k`    - Approximate number of clusters
* `λ`    - Approximate range of kernel function
* `kern` - Kernel function (`:uniform`, `:triangular` or `:epanechnikov`)
* `link` - Linkage function (`:single`, `:average`, `:complete`, `:ward` or `:ward_presquared`)

## References

* Fouedjio, F. 2016. [A hierarchical clustering method for multivariate geostatistical data]
  (https://www.sciencedirect.com/science/article/abs/pii/S2211675316300367)

### Notes

- The range parameter controls the sparsity pattern of the pairwise
  distances, which can greatly affect the computational performance
  of the GHC algorithm. We recommend choosing a range that is small
  enough to connect nearby samples. For example, clustering data over
  a 100x100 Cartesian grid with unit spacing is possible with `λ=1.0`
  or `λ=2.0` but the problem starts to become computationally unfeasible
  around `λ=10.0` due to the density of points.
"""
struct GHC <: ClusteringMethod
  k::Int
  λ::Float64
  kern::Symbol
  link::Symbol
end

function GHC(k, λ; kern=:epanechnikov, link=:ward)
  # sanity checks
  @assert k > 0 "invalid number of clusters"
  @assert λ > 0 "invalid kernel range"
  @assert kern ∈ [:uniform,:triangular,:epanechnikov] "invalid kernel function"
  @assert link ∈ [:single,:average,:complete,:ward,:ward_presquared] "invalid linkage function"
  GHC(k, λ, kern, link)
end

function partition(data, method::GHC)
  # GHC parameters
  k    = method.k
  λ    = method.λ
  kern = method.kern
  link = method.link

  # dissimilarity matrix
  D = ghc_dissimilarity_matrix(data, kern, λ)

  # classical hierarchical clustering
  tree = hclust(D, linkage=link)

  # cut tree to produce clusters
  labels = cutree(tree, k=k)

  # convert labels to subsets
  maxlabel = maximum(labels)
  subsets  = [Int[] for i in 1:maxlabel]
  for (i, l) in enumerate(labels)
    push!(subsets[l], i)
  end

  # return partition
  Partition(data, subsets)
end

function ghc_dissimilarity_matrix(data, kern, λ)
  # retrive domain/table
  𝒟 = domain(data)
  𝒯 = values(data)

  # kernel matrix
  K = ghc_kernel_matrix(kern, λ, 𝒟)

  # difference matrices
  Δ = ghc_diff_matrices(𝒯)

  # sum of cross-variograms
  Γ = ghc_variogram_sum(K, Δ)
end

function ghc_kernel_matrix(kern, λ, 𝒟)
  # kernel function
  fn    = kernfun[kern]
  Kλ(h) = fn(h, λ=λ)

  # collect coordinates
  coords = [coordinates(centroid(𝒟, i)) for i in 1:nelements(𝒟)]

  # lag matrix
  H = pairwise(Euclidean(), coords)

  # kernel matrix
  K = Kλ.(H)

  # return sparse version
  sparse(K)
end

function ghc_diff_matrices(𝒯)
  # covariates as columns
  covars = Tables.columntable(𝒯)

  # number of covariates
  p = length(covars)

  # one matrix per covariate pair
  Δ = Matrix{Matrix{Float64}}(undef, p, p)
  @inbounds for j in 1:p
    Zj = ghc_normalize(covars[j])
    Δj = pairwise(Euclidean(), Zj)
    for i in j+1:p
      Zi = ghc_normalize(covars[i])
      Δi = pairwise(Euclidean(), Zi)
      Δ[i,j] = Δi .* Δj
    end
    Δ[j,j] = Δj .* Δj
    for i in 1:j-1
      Δ[i,j] = Δ[j,i] # leverage the symmetry
    end
  end

  Δ
end

function ghc_variogram_sum(K, Δ)
  n = size(K, 1)
  Γ = zeros(n, n)
  for Δₒ in Δ # for each covariate pair
    # update lower triangular matrix
    @inbounds for j in 1:n
      kj = K[:,j]
      for i in j+1:n
        ki = K[:,i]
        Kij = kron(ki, kj)
        I, W = findnz(Kij)
        num = sum(W .* Δₒ[I], init=0.0)
        den = sum(W, init=0.0)
        iszero(den) || (Γ[i,j] += (1/2) * (num/den))
      end
    end
  end

  # mirror upper triangular matrix
  @inbounds for j in 1:n
    Γ[j,j] = 0.0
    for i in 1:j-1
      Γ[i,j] = Γ[j,i] # leverage the symmetry
    end
  end

  Γ
end

function ghc_normalize(x)
  μ = mean(x)
  σ = std(x, mean=μ)
  (x .- μ) ./ σ
end


text:
__precompile__(true)
module Render

using JuliaParser.Diagnostics: Incomplete, diag
using JuliaParser.Lexer
using JuliaParser.Lexer: TokenStream, eof, here
using RoundingIntegers

import Base: *, getindex, size

export
    # constants
    BEZSTEPS,
    CIRCSTEPS,
    HERMSTEPS,
    SPHSTEPS,
    TORUSTEPS,

    # methods
    dump_ppm_p3,
    dump_ppm_p6,

    addbox!,
    addcurve!,
    addedge!,
    addsphere!,
    addtorus!,

    mkrotate,
    mkscale,
    mktranslate,

    renderfile

### source files

# constants
include("config.jl")

# represents pixels as a manipulatable array
include("display.jl")
include("line.jl")
include("edgematrix.jl")
include("matrixutil.jl")

# parsers
include("parser.jl")

include(joinpath("langs", "mdl.jl"))
using .mdl: mdl_execute, mdl_parser

Render

end

max_stars_repo_name: AnAverageHuman/jlgraphics

max_issues_repo_name: AnAverageHuman/jlgraphics

max_forks_repo_name: AnAverageHuman/jlgraphics


text:
module TestCopy
using Test
using CategoricalArrays
using CategoricalArrays: CategoricalPool

@testset "copy" begin
    pool = CategoricalPool(["d", "c", "b"])
    ordered!(pool, true)
    pool2 = copy(pool)

    @test length(pool2) == 3
    @test pool2.levels == ["d", "c", "b"]
    @test pool2.invindex == Dict("d"=>1, "c"=>2, "b"=>3)
    @test pool2.ordered

    levels!(pool2, ["d", "c", "b", "e"])
    ordered!(pool2, false)

    @test length(pool) == 3
    @test pool.levels == ["d", "c", "b"]
    @test pool.invindex == Dict("d"=>1, "c"=>2, "b"=>3)
    @test pool.ordered
end

end


text:
# Variational Autoencoder
using ASTModels

type LinearLayer <: TypeWithModel
  W
  b
  dict::Model
  function LinearLayer()
    @expr x W::Matrix b::Vector
    new(W, b, Dict("inputs"=>[x], "params" => [W,b], "outputs" => [W*x + b]))
  end
end

function (m1::Model)(m2::Model)
  m1 = convert(Model, m1)
  m2 = convert(Model, m2)
  substitute!(m1["inputs"], m2["outputs"])
  merge_models(m1, m2)
end

function stack(ms::Vector{Union{Model,TypeWithModel}})
  ms = [convert(Model, m) for m in ms]
  m2 = convert(Model, m2)
  substitute!(m1["inputs"], m2["outputs"])
  merge_models(m1, m2)
end

ll1 > ll2 > ll3

type MultiLayer <: TypeWithModel
  layers
  dict::Model

end

@expr a b c

# TODO think about a straightforward way to build up complex models
# usually one would use functions, however functions loose there parameters... while this one keeps track of parameters per Model level
merge(LinearLayer(a)


text:
using Unitful

"""
Generic type representing an atomic species.
"""
abstract type Species end

"""
Atomic species with only one (relevant) electron – all configurations spin-1/2 –
and no hyperfine structure.
"""
type NoHyperfineOneElectronSpecies <: Species
    """
    Energies for different levels.

    The point of reference is chosen arbitrarily.
    """
    energies::Dict{NoHyperfineNumberSpec, Quantity}

    """
    Einstein A coefficients for (lower, upper) pair of levels.

    The sum of all A coefficients for a given upper level is the reciprocal
    level lifetime, so this is the linewidth contribution in angular units.
    """
    einstein_as::Dict{Tuple{NoHyperfineNumberSpec,
        NoHyperfineNumberSpec}, Quantity}
end

"""
Returns the frequency of a given transition (in angular units).

An error is raised if the two levels are not connected by a known transition or
if the levels are incorrectly ordered.
"""
function transition_frequency(species::NoHyperfineOneElectronSpecies, lower, upper)
    # TODO: Nicer errors on wrong keys.
    e1 = species.energies[NoHyperfineNumberSpec(lower)]
    e2 = species.energies[NoHyperfineNumberSpec(upper)]

    if e1 > e2
        throw(ArgumentError("'$lower' is of higher energy than '$upper'"))
    end

    uconvert(THz, (e2 - e1) / u"ħ")
end

"""
Returns the Einstein A coefficient for the given two levels.

The sum of all A coefficients for a given upper level is the reciprocal
level lifetime, so this is the linewidth contribution in angular units.

Returns null if there is no decay from upper to lower.
"""
function einstein_a(species::NoHyperfineOneElectronSpecies, lower, upper)::Nullable{Quantity}
    get(species.einstein_as, (NoHyperfineNumberSpec(lower), NoHyperfineNumberSpec(upper)), Nullable{Quantity}())
end

"""
Returns the lifetime of the given level.

This is the reciprocal of the sum for all the decay rates from the level.

Returns null if there are no decay channels defined from the given level.
"""
function lifetime(species::NoHyperfineOneElectronSpecies, level)::Nullable{Quantity}
    nhns = NoHyperfineNumberSpec(level)
    as = values(filter((l, v) -> l[2] == nhns, species.einstein_as))
    if isempty(as)
        return Nullable{Quantity}()
    end
    uconvert(s, 1 / sum(as))
end

"""
Returns the saturation intensity for the transition between the two levels.

An error is raised if the two levels are not connected by a known transition.
"""
function saturation_intensity(species::NoHyperfineOneElectronSpecies, lower, upper)
    ω = transition_frequency(species, lower, upper)
    τ = get(lifetime(species, upper))
    uconvert(W / m^2, u"ħ" * ω^3 / (6 * π * τ * u"c"^2))
end

function clebsch_gordan(species::NoHyperfineOneElectronSpecies, lower, upper)
end

export Species, NoHyperfineOneElectronSpecies, einstein_a, lifetime, saturation_intensity


text:
using BinaryBuilder

cuda_version = v"10.1.243"  # NOTE: could be less specific

script = raw"""
cd ${WORKSPACE}/srcdir
if [[ ${target} == x86_64-linux-gnu ]]; then
    cd libcutensor
    find .

    install_license license.pdf

    mv lib/10.1/libcutensor.so* ${libdir}
    mv include/* ${prefix}/include
fi
"""

include("../common.jl")

max_stars_repo_name: kalmarek/Yggdrasil

max_issues_repo_name: kalmarek/Yggdrasil

max_forks_repo_name: kalmarek/Yggdrasil


text:
# Julia wrapper for header: /usr/local/include/libavcodec/d3d11va.h
# Automatically generated using Clang.jl wrap_c, version 0.0.0

export
    av_d3d11va_alloc_context

function av_d3d11va_alloc_context()
    ccall((:av_d3d11va_alloc_context,libavcodec),Ptr{AVD3D11VAContext},())
end

max_stars_repo_name: asafasban/AAVideoIO

max_issues_repo_name: asafasban/AAVideoIO

max_forks_repo_name: asafasban/AAVideoIO


text:
############################################################################################
"Abstract type where more tempering methods have to be dispatched on."
abstract type TemperingMethod end

############################################################################################
# Include files
include("iteration.jl")
include("joint.jl")

############################################################################################
# Export
export
    TemperingMethod


text:
srand(0)

facts("qraddrow") do

    m, n = 3, 3
    A = randn(m,m)
    Q, R = qr(A)
    for i in 1:100
        a = randn(m)'
        A = [A; a]
        R = qraddrow(R, a)
        @fact vecnorm( R'R - A'*A ) --> less_than(1e-5)
    end

end


text:
using DistributedArrays

#Code for cumsum using mapreduce.
#We assume that a global array A is stored in a sequence of P partitions
#A1, A2, ..., Ap, where each partition is local to a processor.
#The elements in each subarray Aj are stored in order.

#a map function for the 1st step
#key is a (i,j) pair, and the value Aij is the ith element in the jth partition
map(key::Tuple{Int64,Int64}, Aij::Float64) = (key[2], (key[1], Aij))

#a combine function to compute the sum of the elements in a partition.
#sum takes as input a key, which is the partition id, and an array of values.
#It returns a tuple (1, (key, sum_of_values)), where the artifical key 1
#is used to guarantee that the same reduce worker receives the tuples
#from all the processors.
sum(key::Int64, data) = (1, (key, Base.sum(data))) #sum the values

#a reduce function to compute the exclusive cumsum of the partial sums.
#It takes as input a key, and an array of (partition_id, value) tuples,
#where the partition ids are not necessarily in sorted order.
#It sorts the array by the partition id, and computes the cumsum
#of the values in the sorted array
function exclusive_cumsum(key, value)
  #sort value by partition id
  sort!(value, lt=(a,b)->a[1]<b[1])
  #compute the exclusive cumsum
  initial_value = 0
  for i = 1:length(value)
    temp = value[i][2]
    value[i] = (value[i][1], initial_value)
    initial_value = initial_value + temp
  end
end

#invoke the map function f and combine function g
#map_and_combine(id, f, g, A) = g(id, [f((i, id), A[i])[2][2] for i = 1 : length(A)])
map_and_combine(id, f, g, A) = sum(id, [map((i, id), A[i])[2][2] for i = 1 : length(A)])

#a combine function for the 2nd step
#key is the partition id, data is the array of values
#initial_value is the sum of elements in partitions 1...j-1
function cumsum(key, data, initial_value)
  if length(data) > 0
   data[1] += initial_value
  end
  cumsum!(data, data)
end

function map_and_combine(id, f, g, A, R)
  #A[:] = [f((i, id), A[i])[2][2] for i = 1 : length(A)]
  #[A[i] = map((i, id), A[i])[2][2] for i = 1 : length(A)]
  A[:] = [map((i, id), A[i])[2][2] for i = 1 : length(A)]
  initial_value = R[id][2]
  #g(id, A, initial_value)
  cumsum(id, A, initial_value)
end

function test(A)
#  A_ = convert(Array{Float64, 1}, A)
  t = @elapsed begin
    #mapreduce step 1
    ref = [@spawnat workers()[i] map_and_combine(i, map, sum, localpart(A)) for i =  1:nworkers()]
    #in the reduce step, compute the exclusive cumsum
    partial_sum = [fetch(ref[i])[2] for i = nworkers():-1:1]
    exclusive_cumsum(1, partial_sum)
    #mapreduce step 2
    @sync begin
      [@spawnat workers()[i] map_and_combine(i, map, cumsum, localpart(A), partial_sum) for i =  1:nworkers()]
    end
  end
  println("parallel time ", t) ;
#  out_ = convert(Array{Float64, 1}, A)
#  t1 = @elapsed cumsum!(A_, A_)
#  println("parallel time ", t, " serial time ", t1)
#  println("rel norm ", norm(out_-A_)/abs(A_[end]))
end


text:
import Benchmarks

Benchmarks.@benchmarkable(
    sin_benchmark!,
    nothing,
    sin(2.0),
    nothing
)

r = Benchmarks.execute(sin_benchmark!)

e = Benchmarks.Environment()

writecsv("environment.csv", e)

writecsv("samples.csv", r.samples)

Benchmarks.@benchmarkable(
    digamma_benchmark!,
    nothing,
    digamma(2.0),
    nothing
)

r = Benchmarks.execute(digamma_benchmark!)

# Samples are clearly non-independent, so CI's are probably anti-conservative
x, y = r.samples.n_evals, r.samples.elapsed_times
idx = find(x .== maximum(x))
x = x[idx]
y = y[idx]
n = length(idx)
cor(y[1:(n - 1)], y[2:n])

Benchmarks.@benchmarkable(
    svd2_benchmark!,
    nothing,
    svd(randn(100, 100)),
    nothing
)

r = Benchmarks.execute(svd2_benchmark!)

Benchmarks.@benchmarkable(
    sleep_benchmark!,
    nothing,
    sleep(7.5),
    nothing
)

r = Benchmarks.execute(sleep_benchmark!)

Benchmarks.@benchmark(sin(2.0))
Benchmarks.@benchmark(svd(rand(1000, 1000)))

using Benchmarks

@benchmark svd(rand(1, 1))


text:
include("Header.jl")

struct FrameHeader
    number       ::Int64
    maxData      ::Int64
    minData      ::Int64
    offsetX      ::Int64
    offsetY      ::Int64
    tiltX        ::Float64
    tiltY        ::Float64
    isStimulated ::Bool
    booked1      ::Int64
    booked2      ::Int64
    booked3      ::Int64
    booked4      ::Int64
end

struct Frame
    header   ::FrameHeader
    data     ::Array{Float64, 2}
    subData  ::Union{Array{Float64, 2}, Nothing}
end

max_stars_repo_name: matsunagalab/BioAFM

max_issues_repo_name: matsunagalab/BioAFM

max_forks_repo_name: matsunagalab/BioAFM


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

# TODO: make this a general purpose solution
function Base.cconvert(::Type{Ptr{DiffOptionsStruct}}, pathspecs::AbstractString)
    str_ref = Base.cconvert(Ref{Cstring}, [pathspecs])
    sa = StrArrayStruct(Base.unsafe_convert(Ref{Cstring}, str_ref), 1)
    do_ref = Ref(DiffOptionsStruct(pathspec = sa))
    do_ref, str_ref
end
function Base.unsafe_convert(::Type{Ptr{DiffOptionsStruct}}, rr::Tuple{Ref{DiffOptionsStruct}, Ref{Cstring}})
    Base.unsafe_convert(Ptr{DiffOptionsStruct}, first(rr))
end

function diff_tree(repo::GitRepo, tree::GitTree, pathspecs::AbstractString=""; cached::Bool=false)
    diff_ptr_ptr = Ref{Ptr{Void}}(C_NULL)
    if cached
        @check ccall((:git_diff_tree_to_index, :libgit2), Cint,
                     (Ptr{Ptr{Void}}, Ptr{Void}, Ptr{Void}, Ptr{Void}, Ptr{DiffOptionsStruct}),
                     diff_ptr_ptr, repo.ptr, tree.ptr, C_NULL, isempty(pathspecs) ? C_NULL : pathspecs)
    else
        @check ccall((:git_diff_tree_to_workdir_with_index, :libgit2), Cint,
                     (Ptr{Ptr{Void}}, Ptr{Void}, Ptr{Void}, Ptr{DiffOptionsStruct}),
                     diff_ptr_ptr, repo.ptr, tree.ptr, isempty(pathspecs) ? C_NULL : pathspecs)
    end
    return GitDiff(repo, diff_ptr_ptr[])
end

function diff_tree(repo::GitRepo, oldtree::GitTree, newtree::GitTree)
    diff_ptr_ptr = Ref{Ptr{Void}}(C_NULL)
    @check ccall((:git_diff_tree_to_tree, :libgit2), Cint,
                  (Ptr{Ptr{Void}}, Ptr{Void}, Ptr{Void}, Ptr{Void}, Ptr{DiffOptionsStruct}),
                   diff_ptr_ptr, repo.ptr, oldtree.ptr, newtree.ptr, C_NULL)
    return GitDiff(repo, diff_ptr_ptr[])
end

function GitDiffStats(diff::GitDiff)
    diff_stat_ptr_ptr = Ref{Ptr{Void}}(C_NULL)
    @check ccall((:git_diff_get_stats, :libgit2), Cint,
                  (Ptr{Ptr{Void}}, Ptr{Void}),
                  diff_stat_ptr_ptr, diff.ptr)
    return GitDiffStats(diff.owner, diff_stat_ptr_ptr[])
end

function files_changed(diff_stat::GitDiffStats)
    return ccall((:git_diff_stats_files_changed, :libgit2), Csize_t, (Ptr{Void},), diff_stat.ptr)
end

function insertions(diff_stat::GitDiffStats)
    return ccall((:git_diff_stats_insertions, :libgit2), Csize_t, (Ptr{Void},), diff_stat.ptr)
end

function deletions(diff_stat::GitDiffStats)
    return ccall((:git_diff_stats_deletions, :libgit2), Csize_t, (Ptr{Void},), diff_stat.ptr)
end

function Base.count(diff::GitDiff)
    return ccall((:git_diff_num_deltas, :libgit2), Cint, (Ptr{Void},), diff.ptr)
end

function Base.getindex(diff::GitDiff, i::Integer)
    if i < 1 || i > count(diff)
        throw(BoundsError(diff, (i,)))
    end
    delta_ptr = ccall((:git_diff_get_delta, :libgit2),
                      Ptr{DiffDelta},
                      (Ptr{Void}, Csize_t), diff.ptr, i-1)
    return unsafe_load(delta_ptr)
end

function Base.show(io::IO, diff_stat::GitDiffStats)
    println(io, "GitDiffStats:")
    println(io, "Files changed: $(files_changed(diff_stat))")
    println(io, "Insertions: $(insertions(diff_stat))")
    println(io, "Deletions: $(deletions(diff_stat))")
end

function Base.show(io::IO, diff::GitDiff)
    println(io, "GitDiff:")
    println(io, "Number of deltas: $(count(diff))")
    show(io, GitDiffStats(diff))
end


text:
# Initialise VTK multiblock file (extension .vtm).
# filename: filename with or without the extension (.vtm).
function vtk_multiblock(filename::AbstractString)
    xvtm = XMLDocument()
    xroot = create_root(xvtm, "VTKFile")
    set_attribute(xroot, "type", "vtkMultiBlockDataSet")
    set_attribute(xroot, "version", "1.0")
    if IS_LITTLE_ENDIAN
        set_attribute(xroot, "byte_order", "LittleEndian")
    else
        set_attribute(xroot, "byte_order", "BigEndian")
    end
    new_child(xroot, "vtkMultiBlockDataSet")
    return MultiblockFile(xvtm, add_extension(filename, ".vtm"))
end

"""
    vtk_grid(vtm::MultiblockFile, [filename], griddata...; kwargs...)

Create new dataset file that is added to an existent multiblock file.
The VTK grid is specified by the elements of `griddata`.

If the filename is not given, it is determined automatically from the filename
of the vtm file and the number of existent blocks.
"""
function vtk_grid(vtm::MultiblockFile, vtk_filename::AbstractString,
                  griddata...; kwargs...)
    vtk = vtk_grid(vtk_filename, griddata...; kwargs...)
    push!(vtm, vtk)
    vtk :: DatasetFile
end

function vtk_grid(vtm::MultiblockFile, griddata...; kwargs...)
    vtm_basename, _ = splitext(vtm.path)
    vtk_basename = string(vtm_basename, "_", 1 + length(vtm.blocks))
    vtk_grid(vtm, vtk_basename, griddata...; kwargs...)
end

"""
    vtk_grid(vtb::vtkBlock, [filename], griddata...; kwargs...)

Create new dataset file that is added to an existent VTKBlock.
The VTK grid is specified by the elements of `griddata`.

If the filename is not given, it is determined automatically from the filename
of the vtb file and the number of existent blocks.
"""
function vtk_grid(vtb::VTKBlock, vtk_filename::AbstractString,
                  griddata...; kwargs...)
    vtk = vtk_grid(vtk_filename, griddata...; kwargs...)
    multiblock_add_block(vtb, vtk, vtk_filename)
    vtk :: DatasetFile
end

function vtk_grid(vtb::VTKBlock, griddata...; kwargs...)
    new_block_number = length(vtb.blocks) + 1
    block_name = attribute(vtb.xelm, "name", required=false)
    if block_name != nothing
        vtk_basename = "$(name)_$(new_block_number)"
    else
        block_index = attribute(vtb.xelm, "index")
        vtk_basename = "block$(block_index)_$(new_block_number)"
    end

    vtk_grid(vtb, vtk_basename, griddata...; kwargs...)
end

"""
    vtk_save(vtm::MultiblockFile)

Save and close multiblock file (.vtm).
The VTK files included in the multiblock file are also saved.
"""
function vtk_save(vtm::MultiblockFile)
    outfiles = [vtm.path]::Vector{String}
    for vtk in vtm.blocks
        append!(outfiles, vtk_save(vtk))
    end
    if isopen(vtm)
        save_file(vtm.xdoc, vtm.path)
        close(vtm)
    end
    return outfiles
end

function vtk_save(vtm::VTKBlock)
    # Saves VTKBlocks.
    outfiles = String[]
    for vtk in vtm.blocks
        append!(outfiles, vtk_save(vtk))
    end
    return outfiles
end

function multiblock_add_block(vtm::MultiblockFile, vtk::VTKFile, name="")
    # Add VTK file as a new block to a multiblock file.

    # Find vtkMultiBlockDataSet node
    xroot = root(vtm.xdoc)
    xMBDS = find_element(xroot, "vtkMultiBlockDataSet")

    # DataSet node
    fname = splitdir(vtk.path)[2]

    xDataSet = new_child(xMBDS, "DataSet")
    nblock = length(vtm.blocks)
    set_attribute(xDataSet, "index", "$nblock")
    set_attribute(xDataSet, "file",  fname)
    if name != ""
        set_attribute(xDataSet, "name",  name)
    end

    # Add the block file to vtm.
    push!(vtm.blocks, vtk)

    nothing
end

function multiblock_add_block(vtm::MultiblockFile, name="")
    # Add VTK block to a multiblock file.

    # Find vtkMultiBlockDataSet node
    xroot = root(vtm.xdoc)
    xMBDS = find_element(xroot, "vtkMultiBlockDataSet")

    # Add the block metadata to the XML.
    xBlock = new_child(xMBDS, "Block")
    nblock = length(vtm.blocks)
    set_attribute(xBlock, "index", "$nblock")
    if name != ""
        set_attribute(xBlock, "name",  name)
    end

    # Create the new block.
    block = VTKBlock(xBlock)

    # Add the block to vtm.
    push!(vtm.blocks, block)

    # Return the new block so the user can add VTKFiles or VTKBlocks under it,
    # if desired.
    return block
end

function multiblock_add_block(vtb::VTKBlock, vtk::VTKFile, name="")
    # Add VTKFile to a VTKBlock.

    # DataSet node
    fname = splitdir(vtk.path)[2]

    xDataSet = new_child(vtb.xelm, "DataSet")
    nblock = length(vtb.blocks)
    set_attribute(xDataSet, "index", "$nblock")
    set_attribute(xDataSet, "file",  fname)
    if name != ""
        set_attribute(xDataSet, "name",  name)
    end

    # Add the block to vtb.
    push!(vtb.blocks, vtk)

    nothing
end

function multiblock_add_block(vtb::VTKBlock, name="")
    # Add VTK block to a VTK Block.

    xBlock = new_child(vtb.xelm, "Block")
    nblock = length(vtb.blocks)
    set_attribute(xBlock, "index", "$nblock")
    if name != ""
        set_attribute(xBlock, "name",  name)
    end

    # Create the new block.
    block = VTKBlock(xBlock)

    # Add the block to vtb.
    push!(vtb.blocks, block)

    # Return the new block so the user can add VTKFiles or VTKBlocks under it,
    # if desired.
    return block
end

Base.push!(vtm::MultiblockFile, vtk::VTKFile) = multiblock_add_block(vtm, vtk)
Base.push!(vtb::VTKBlock, vtk::VTKFile) = multiblock_add_block(vtb, vtk)


text:
using TaskGraphs
using Documenter

makedocs(;
    modules=[TaskGraphs],
    authors="kylebrown <kylejbrown17@gmail.com> and contributors",
    repo="https://github.com/kylejbrown17/TaskGraphs.jl",
    sitename="TaskGraphs.jl",
    format=Documenter.HTML(;
        prettyurls=get(ENV, "CI", "false") == "true",
        canonical="https://kylejbrown17.github.io/TaskGraphs.jl",
        assets=String[],
    ),
    pages=[
        "Home" => "index.md",
        "Getting Started" => "getting_started.md",
        "Profiling" => "profiling.md",
        "Core Types and Methods" => "library.md",
        "API Reference" => "reference.md",
    ],
)

deploydocs(;
    repo="github.com/kylejbrown17/TaskGraphs.jl",
)


text:
Base.convert(::Type{M}, v::Variable) where {Vars, M <: Monomial{Vars}} = convert(M, Monomial(v))
Base.convert(::Type{Monomial}, v::Variable) = Monomial(v)
Base.convert(::Type{Term{T, M1}}, m::Monomial) where {T, M1} = Term(one(T), convert(M1, m))
Base.convert(::Type{Term{T, M}}, v::Variable) where {T, M} = Term(one(T), convert(M, v))
Base.convert(T::Type{Polynomial{C1, T1, V1}}, p::Polynomial) where {C1, T1, V1} = T(convert(V1, p.terms))
# Break ambibuity
Base.convert(T::Type{Polynomial{C1, T1, V1}}, x::MP.AbstractTermLike) where {C1, T1, V1} = convert(T, Polynomial(convert(T1, x)))

MP.convertconstant(T::Type{Term{T1, M1}}, α) where {T1, M1} = T(convert(T1, α), M1())
MP.convertconstant(T::Type{Polynomial{C1, T1, V1}}, α) where {C1, T1, V1} = convert(T, Polynomial(convert(T1, α)))

Base.convert(T::Type{Monomial{V}}, m::Monomial) where {V} = convert(Monomial{V, nvariables(T)}, m)

@pure function matchindices(::Type{Monomial{V1, N1}}, ::Type{Monomial{V2, N2}}) where {V1, N1, V2, N2}
    i2 = 1
    inds = ntuple(i -> begin
        if i2 > N2
            0
        elseif V1[i] === V2[i2]
            i2 += 1
            i2 - 1
        else
            0
        end
    end, Val{N1}())
    if i2 <= N2
        throw(InexactError(:matchindices, Monomial{V1, N1}, Monomial{V2, N2}))
    end
    inds
end

function Base.convert(::Type{Monomial{V1, N1}}, m::Monomial) where {V1, N1}
    inds = matchindices(Monomial{V1, N1}, typeof(m))
    exps = ntuple(i -> begin
        @inbounds ii = inds[i]
        if ii == 0
            0
        else
            m.exponents[ii]
        end
    end, Val{N1}())
    Monomial{V1, N1}(exps)
end

Base.convert(::Type{Term{T1, M1}}, t::Term) where {T1, M1} = Term{T1, M1}(MA.scaling_convert(T1, t.coefficient), convert(M1, t.monomial))
MP.polynomial!(v::AbstractVector{<:Term}, ::MP.SortedUniqState) = Polynomial(v)
function MP.polynomial(p::P, ::Type{C}) where {P<:PolynomialLike, C}
    convert(polynomialtype(P, C), p)
end

function Base.convert(::Type{Variable}, mono::Monomial)
    var = _mono2var(mono, powers(mono)...)
    var === nothing && throw(InexactError(:convert, Variable, mono))
    return var
end

function _checknovar(mono) end
function _checknovar(mono, ve, ves...)
    if iszero(ve[2])
        _checknovar(mono, ves...)
    else
        throw(InexactError(:convert, Variable, mono))
    end
end
function _mono2var(mono, ve, ves...)
    if iszero(ve[2])
        _mono2var(mono, ves...)
    elseif isone(ve[2])
        _checknovar(mono, ves...)
        ve[1]
    else
        throw(InexactError(:convert, Variable, mono))
    end
end
_mono2var(mono) = throw(InexactError(:convert, Variable, mono))


text:
using SpikeGLM
using Base.Test

# write your own tests here
A = randn(100, 5)
B = randn(100, 3)
C = HCatMatrix(A, B)
D = [A B]
E = randn(100, 4)

a = randn(100)
b = randn(8)

@test_approx_eq C*b D*b
@test_approx_eq C'C D'D
@test_approx_eq C'E D'E
@test_approx_eq C'a D'a
@test_approx_eq C.'C D.'D
@test_approx_eq C.'E D.'E
@test_approx_eq C.'a D.'a
@test_approx_eq scale!(a, C) scale!(a, D)

A = randn(3, 2)
B = randn(5, 7)
densekron = kron(A, B)
kronprod = KroneckerProduct(A, B)
@test_approx_eq densekron SpikeGLM.kron!(similar(densekron), A, B)
@test_approx_eq densekron kronprod
@test_approx_eq densekron convert(Matrix, kronprod)

@test_approx_eq densekron'densekron kronprod'kronprod

v = randn(14)
@test_approx_eq densekron*v kronprod*v
Y = randn(14, 3)
@test_approx_eq densekron*Y kronprod*Y

v = randn(15)
@test_approx_eq densekron'v kronprod'v
@test_approx_eq v'densekron v'kronprod
Y = randn(15, 3)
@test_approx_eq densekron'Y kronprod'Y

@test_approx_eq kron(A, ones(1, size(A, 2))).*kron(ones(1, size(A, 2)), A) SpikeGLM.rowtensor(A)
@test_approx_eq kron(B, ones(1, size(B, 2))).*kron(ones(1, size(B, 2)), B) SpikeGLM.rowtensor(B)

@test_approx_eq SpikeGLM.weightmul(densekron, v) SpikeGLM.weightmul(kronprod, v)
@test_approx_eq SpikeGLM.weightmul([densekron Y], v) SpikeGLM.weightmul(HCatMatrix(kronprod, Y), v)

A = randn(10, 7)
B = randn(10, 10)
Y = randn(100, 3)
v = randn(100)
c1 = coef(fit(GeneralizedLinearModel, [kron(A, B) Y], v, Normal(), IdentityLink()))
c2 = coef(fit(GeneralizedLinearModel, HCatMatrix(KroneckerProduct(A, B), Y), v, Normal(), IdentityLink()))

const DATADIR = joinpath(dirname(@__FILE__), "data")

#= in R
	library(splines)
	x <- bs(seq(0, 1000), knots=seq(100, 900, 100), degree=3)
	write.table(x, "splines.csv", row.names=F, col.names=F)
=#
@test_approx_eq bsplines(0:1000, 3, 0:100:1000) readdlm(joinpath(DATADIR, "splines.txt"))

#= with neuroGLM
    bs = basisFactory.makeSmoothTemporalBasis('raised cosine', 1000, 20, @(x)x);
    x = bs.B
    save -ascii -double raisedcosines.txt x
 =#
@test_approx_eq raisedcosines(1:1000, 20) readdlm(joinpath(DATADIR, "raisedcosines.txt"))

#= with neuroGLM
    bs = basisFactory.makeNonlinearRaisedCos(10, 1, [0 100], 2);
    x = bs.B
    save -ascii -double raisedcosines.txt x
 =#
@test_approx_eq raisedcosines(1, 10, 0, 100, 2) readdlm(joinpath(DATADIR, "nonlinear_raisedcosines.txt"))


text:
function H5RTM(;
  model::JUDI.Model,
  opt::JUDI.JUDIOptions,
  q::JUDI.judiVector,
  dobs::JUDI.judiVector)

  h5geo = pyimport("h5geopy._h5geo")

  ###################################################################################################

  # Setup operators
  Pr = judiProjection(dobs.geometry)
  F = judiModeling(model; options=opt)
  Ps = judiProjection(q.geometry)
  J = judiJacobian(Pr*F*adjoint(Ps), q)

  # RTM
  rtm = adjoint(J)*dobs

  H5WritePhysicalParameter(
    cntName="$(opt.file_path)/rtm.h5",
    objName="rtm",
    cntCreationType=h5geo.CreationType.OPEN_OR_CREATE,
    objCreationType=h5geo.CreationType.CREATE_UNDER_NEW_NAME,
    php=rtm
  )

  @info "RTM finished\n"
end


text:
@testset "get_datetime_for_doy_hour summer" begin
    hours = [0,π,24]
    dts = get_datetime_for_doy_hour.(1, hours; year = 2021)
    @test dts[1] == DateTime(2021,1,1)
    @test dts[3] == DateTime(2021,1,2)
    @test dts[1] < dts[2]  < dts[3]
end

@testset "Dresden summer" begin
    hours = 8:16
    potRadSolar = potential_radiation.(160, hours, 39.94, -5.77; timezone = tz"UTC+1")
    @test eltype(potRadSolar) == Float64
    expSolar = [
      484.152670743821, 717.876981534078, 925.130678985721,
      1091.78976612035, 1206.4967015669, 1261.43439723686, 1252.85893995917,
      1181.35473297567, 1051.79466982602]
    @test all(.≈(potRadSolar, expSolar, rtol = 0.02))
    #
    # test Float32
    potRadSolar = potential_radiation.(160, hours, 39.94f0, -5.77f0; timezone = tz"UTC+1")
    @test eltype(potRadSolar) == Float32
end


text:
const suit_names = ["♣", "♢", "♡", "♠"]
const rank_names = ["A", "2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K"]

struct Card
    suit:: Int64
    rank:: Int64
    function Card(suit::Int64, rank::Int64)
        @assert(1 ≤ suit ≤ 4, "suit is not between 1 and 4")
        @assert(1 ≤ rank ≤ 13, "rank is not between 1 and 13")
        new(suit, rank)
    end
end

function Base.show(io::IO, card::Card)
    print(io, rank_names[card.rank], suit_names[card.suit])
end

qd = Card(2, 12)
kh = Card(3,13)

import Base.isless
function isless(c1::Card, c2::Card)
    (c1.suit, c1.rank) < (c2.suit, c2.rank)
end

qd < kh
kh < qd

using Test
@test Card(1, 4) < Card(2, 4)
@test Card(1, 3) < Card(1, 4)
# @test Card(1, 4) < Card(1, 3)

abstract type CardSet<:Any end

struct Deck <: CardSet
    cards :: Array{Card, 1}
end

function Deck()
    deck = Deck(Card[])
    for suit in 1:4
        for rank in 1:13
            push!(deck.cards, Card(suit, rank))
        end
    end
    deck
end

function Base.show(io::IO, deck::Deck)
    for card in deck.cards
        print(io, card, " ")
    end
    println(io)
end

Deck()

function Base.pop!(deck::Deck)
    pop!(deck.cards)
end

function Base.push!(deck::Deck, card::Card)
    push!(deck.cards, card)
    #deck
    nothing
end

using Random

function Random.shuffle!(deck::Deck)
    shuffle!(deck.cards)
    deck
end

d = Deck()

Random.shuffle!(d)
d

function Base.sort!(deck::Deck)
    sort!(deck.cards)  #uses Base.isless(::Card, ::Card)
    deck
end

d
sort!(d)
d

d isa Deck

d isa CardSet

struct Hand <: CardSet
    cards :: Array{Card,1}
    label :: String
end

function Hand(label::String="")
    Hand(Card[], label)
end

hand = Hand("my new hand")

hand

function Base.show(io::IO, cs::CardSet)
    for card in cs.cards
        print(io, card, " ")
    end
end

function Base.pop!(cs::CardSet)
    pop!(cs.cards)
end

function Base.push!(cs::CardSet, card::Card)
    push!(cs.cards, card)
    nothing
end

deck = Deck()
deck

push!(hand, Card(3,3))
push!(hand, Card(3,9))
@show hand
pop!(hand)
pop!(hand)

@show deck;
push!(hand, pop!(deck))
@show hand
@show deck

function move!(cs1::CardSet, cs2::CardSet, n::Int)
    @assert 1 ≤ n ≤ length(cs1.cards)
    for i in 1:n
        card = pop!(cs1)
        push!(cs2, card)
    end
    nothing
end

move!(deck, hand, 12)

@show deck;
@show hand;


text:
@testset "Hamiltonian splitting with spin" begin
    import GEMPIC: get_x, get_charge, add_charge!
    import GEMPIC: operatorHp1, operatorHp2, operatorHE, operatorHB

    # Tolerance for comparison of real numbers: set it here!
    eqv_tol = 1.0e-14

    # Set parameters
    n_particles = 2
    eta_min = 0.0
    eta_max = 4π
    num_cells = 10
    delta_t = 0.1
    degree_smoother = 3
    rnd_seed = 10

    mesh = OneDGrid(eta_min, eta_max, num_cells)

    pg = ParticleGroup{1,1}(n_particles; n_spin=3)

    # Initialize kernel smoothers
    kernel_smoother_1 = ParticleMeshCoupling1D(
        mesh, n_particles, degree_smoother - 1, :galerkin
    )

    kernel_smoother_0 = ParticleMeshCoupling1D(
        mesh, n_particles, degree_smoother, :galerkin
    )

    # Initialize Maxwell solver
    maxwell_solver = Maxwell1DFEM(mesh, degree_smoother)

    n_dofs = kernel_smoother_0.n_dofs

    ex = zeros(Float64, n_dofs)
    efield = ones(Float64, n_dofs)
    bfield = ones(Float64, n_dofs)
    efield_ref = zeros(Float64, n_dofs)
    bfield_ref = zeros(Float64, n_dofs)
    rho = zeros(Float64, n_dofs)

    for i_part in 1:n_particles
        xi = get_x(pg, i_part)[1]
        wi = get_charge(pg, i_part)
        add_charge!(rho, kernel_smoother_0, xi, wi)
    end

    @test true
end


text:
n_values  = [10, 20, 50, 100, 150, 200]
k_values  = [10, 20, 50, 100, 150, 200]
m_values  = [10, 20, 50, 100, 150, 200]

function matmul_pack_ab!(C, A, B)
    M, N = size(C); K = size(B,1)
    zc, za, zb = Octavian.zstridedpointer.((C,A,B))
    nspawn = min(Threads.nthreads(), Octavian.num_cores())
    GC.@preserve C A B begin
        if nspawn > 1
            Octavian.matmul_pack_A_and_B!(
                zc, za, zb, Octavian.StaticInt{1}(), Octavian.StaticInt{0}(), M, K, N, nspawn,
                Octavian.W₁Default(), Octavian.W₂Default(), Octavian.R₁Default(), Octavian.R₂Default()
            )
        else
            Octavian.matmul_st_pack_A_and_B!(
                zc, za, zb, Octavian.StaticInt{1}(), Octavian.StaticInt{0}(), M, K, N,
                Octavian.W₁Default(), Octavian.W₂Default(), Octavian.R₁Default(), Octavian.R₂Default(), 0
            )
        end
    end
    C
end

testset_name_suffix = "(coverage)"

include("_matmul.jl")


text:
"""
$(TYPEDEF)
$(TYPEDFIELDS)

where `exclude_prefixes` are prefixes of directories to exclude.

### Example
```
Repo("https://github.com", "JuliaLang/julia", [], ["test"])
```
"""
struct Repo
    host::String
    name::String
    tags_predicates::Vector{Function}
    exclude_prefixes::Vector{String}
end

any_tag(tags) = true

"""
Ensures that suggestions for a repository are not too new.

$(SIGNATURES)
"""
function version(tags, n::Number)
    check(t) = isa(t, Number) ? n<t : false
    !any(check, tags)
end
version(n::Number) = Base.Fix2(version, n)

function default_predicate(tags)
    decr(t) = t == "performance-decrease"
    disabled(t) = t == "disabled"
    all(!decr, tags) &&
        version(tags, 1.0) &&
        all(!disabled, tags)
end

default_excludes = ["test"]

Repo(host, name; predicates=[default_predicate], exclude=default_excludes) =
    Repo(host, name, predicates, exclude)

is_production()::Bool = haskey(ENV, "CI")

repositories(; production=is_production()) = production ?
    [
        Repo("https://github.com", "Evizero/UnicodePlots.jl"),
        Repo("https://github.com", "FRBNY-DSGE/SMC.jl"),
        Repo("https://github.com", "FluxML/MacroTools.jl"),
        Repo("https://github.com", "FluxML/Metalhead.jl"),
        Repo("https://github.com", "FluxML/Zygote.jl"),
        Repo("https://github.com", "GiovineItalia/Compose.jl"),
        Repo("https://github.com", "GiovineItalia/Gadfly.jl"),
        Repo("https://github.com", "JuliaCollections/AbstractTrees.jl"),
        Repo("https://github.com", "JuliaCollections/DataStructures.jl"),
        Repo("https://github.com", "JuliaCollections/FunctionalCollections.jl"),
        Repo("https://github.com", "JuliaCollections/IterTools.jl"),
        Repo("https://github.com", "JuliaCollections/LRUCache.jl"),
        Repo("https://github.com", "JuliaCollections/Memoize.jl"),
        Repo("https://github.com", "JuliaCollections/OrderedCollections.jl"),
        Repo("https://github.com", "JuliaControl/ControlSystems.jl"),
        Repo("https://github.com", "JuliaData/CSV.jl"),
        Repo("https://github.com", "JuliaData/DataFrames.jl"),
        Repo("https://github.com", "JuliaData/DataFramesMeta.jl"),
        Repo("https://github.com", "JuliaData/Feather.jl"),
        Repo("https://github.com", "JuliaData/Tables.jl"),
        Repo("https://github.com", "JuliaData/YAML.jl"),
        Repo("https://github.com", "JuliaDatabases/MySQL.jl"),
        Repo("https://github.com", "JuliaDatabases/PostgreSQL.jl"),
        Repo("https://github.com", "JuliaDatabases/Redis.jl"),
        Repo("https://github.com", "JuliaDatabases/SQLite.jl"),
        Repo("https://github.com", "JuliaDebug/Debugger.jl"),
        Repo("https://github.com", "JuliaDebug/Gallium.jl"),
        Repo("https://github.com", "JuliaDebug/JuliaInterpreter.jl"),
        Repo("https://github.com", "JuliaDiff/ChainRules.jl"),
        Repo("https://github.com", "JuliaDiff/ChainRulesCore.jl"),
        Repo("https://github.com", "JuliaDiff/FiniteDiff.jl"),
        Repo("https://github.com", "JuliaDiff/FiniteDifferences.jl"),
        Repo("https://github.com", "JuliaDiff/ForwardDiff.jl"),
        Repo("https://github.com", "JuliaDiff/ReverseDiff.jl"),
        Repo("https://github.com", "JuliaDiff/SparseDiffTools.jl"),
        Repo("https://github.com", "JuliaDiff/TaylorSeries.jl"),
        Repo("https://github.com", "JuliaDocs/DocStringExtensions.jl"),
        Repo("https://github.com", "JuliaDocs/Documenter.jl"),
        Repo("https://github.com", "JuliaDynamics/Agents.jl"; predicates=[version(1.5)]),
        Repo("https://github.com", "JuliaDynamics/ChaosTools.jl"),
        Repo("https://github.com", "JuliaDynamics/DrWatson.jl"),
        Repo("https://github.com", "JuliaDynamics/DynamicalBilliards.jl"),
        Repo("https://github.com", "JuliaDynamics/DynamicalSystems.jl"),
        Repo("https://github.com", "JuliaDynamics/DynamicalSystemsBase.jl"),
        Repo("https://github.com", "JuliaDynamics/Entropies.jl"),
        Repo("https://github.com", "JuliaGPU/AMDGPU.jl"),
        Repo("https://github.com", "JuliaGPU/ArrayFire.jl"),
        Repo("https://github.com", "JuliaGPU/CUDA.jl"),
        Repo("https://github.com", "JuliaGPU/OpenCL.jl"),
        Repo("https://github.com", "JuliaGaussianProcesses/AbstractGPs.jl"),
        Repo("https://github.com", "JuliaGaussianProcesses/KernelFunctions.jl"),
        Repo("https://github.com", "JuliaGraphs/GraphPlot.jl"),
        Repo("https://github.com", "JuliaGraphs/LightGraphs.jl"),
        Repo("https://github.com", "JuliaIO/EzXML.jl"),
        Repo("https://github.com", "JuliaIO/Formatting.jl"),
        Repo("https://github.com", "JuliaIO/HDF5.jl"),
        Repo("https://github.com", "JuliaIO/JLD.jl"),
        Repo("https://github.com", "JuliaIO/MAT.jl"),
        Repo("https://github.com", "JuliaIO/VideoIO.jl"),
        Repo("https://github.com", "JuliaImages/ImageView.jl"),
        Repo("https://github.com", "JuliaImages/Images.jl"),
        Repo("https://github.com", "JuliaInterop/Clang.jl"),
        Repo("https://github.com", "JuliaInterop/Cxx.jl"),
        Repo("https://github.com", "JuliaInterop/MATLAB.jl"),
        Repo("https://github.com", "JuliaInterop/RCall.jl"),
        Repo("https://github.com", "JuliaInterop/ZMQ.jl"),
        Repo("https://github.com", "JuliaLang/Compat.jl"),
        Repo("https://github.com", "JuliaLang/Downloads.jl"),
        Repo("https://github.com", "JuliaLang/IJulia.jl"),
        Repo("https://github.com", "JuliaLang/MbedTLS.jl"),
        Repo("https://github.com", "JuliaLang/PackageCompiler.jl"),
        Repo("https://github.com", "JuliaLang/Pkg.jl"),
        Repo("https://github.com", "JuliaLang/PkgDev.jl"),
        Repo("https://github.com", "JuliaLang/Statistics.jl"),
        Repo("https://github.com", "JuliaLang/TOML.jl"),
        Repo("https://github.com", "JuliaLang/Tokenize.jl"),
        Repo("https://github.com", "JuliaLang/julia"),
        Repo("https://github.com", "JuliaML/LossFunctions.jl"),
        Repo("https://github.com", "JuliaML/MLDataUtils.jl"),
        Repo("https://github.com", "JuliaML/MLLabelUtils.jl"),
        Repo("https://github.com", "JuliaML/Reinforce.jl"),
        Repo("https://github.com", "JuliaManifolds/Manifolds.jl"),
        Repo("https://github.com", "JuliaManifolds/ManifoldsBase.jl"),
        Repo("https://github.com", "JuliaManifolds/Manopt.jl"),
        Repo("https://github.com", "JuliaMath/Calculus.jl"),
        Repo("https://github.com", "JuliaMath/Combinatorics.jl"),
        Repo("https://github.com", "JuliaMath/DoubleFloats.jl"),
        Repo("https://github.com", "JuliaMath/FFTW.jl"),
        Repo("https://github.com", "JuliaMath/FixedPointNumbers.jl"),
        Repo("https://github.com", "JuliaMath/HCubature.jl"),
        Repo("https://github.com", "JuliaMath/Interpolations.jl"),
        Repo("https://github.com", "JuliaMath/Polynomials.jl"),
        Repo("https://github.com", "JuliaMath/Roots.jl"),
        Repo("https://github.com", "JuliaMath/SpecialFunctions.jl"),
        Repo("https://github.com", "JuliaNLSolvers/LsqFit.jl"),
        Repo("https://github.com", "JuliaNLSolvers/NLsolve.jl"),
        Repo("https://github.com", "JuliaNLSolvers/Optim.jl"),
        Repo("https://github.com", "JuliaPackaging/BinaryBuilder.jl"),
        Repo("https://github.com", "JuliaPackaging/BinaryBuilderBase.jl"),
        Repo("https://github.com", "JuliaPackaging/PkgServer.jl"),
        Repo("https://github.com", "JuliaPackaging/Requires.jl"),
        Repo("https://github.com", "JuliaPackaging/Yggdrasil"),
        Repo("https://github.com", "JuliaPlots/Makie.jl"),
        Repo("https://github.com", "JuliaPlots/Plots.jl"),
        Repo("https://github.com", "JuliaPy/Pandas.jl"),
        Repo("https://github.com", "JuliaPy/PyCall.jl"),
        Repo("https://github.com", "JuliaPy/PyPlot.jl"),
        Repo("https://github.com", "JuliaRegistries/CompatHelper.jl"),
        Repo("https://github.com", "JuliaRegistries/Registrator.jl"),
        Repo("https://github.com", "JuliaStats/Distributions.jl"),
        Repo("https://github.com", "JuliaStats/GLM.jl"),
        Repo("https://github.com", "JuliaStats/HypothesisTests.jl"),
        Repo("https://github.com", "JuliaStats/Lasso.jl"),
        Repo("https://github.com", "JuliaStats/MixedModels.jl"),
        Repo("https://github.com", "JuliaStats/StatsKit.jl"),
        Repo("https://github.com", "JuliaStats/StatsModels.jl"),
        Repo("https://github.com", "JuliaTPU/XLA.jl"),
        Repo("https://github.com", "JuliaWeb/HTTP.jl"),
        Repo("https://github.com", "JuliaWeb/WebSockets.jl"),
        Repo("https://github.com", "JunoLab/Weave.jl"),
        Repo("https://github.com", "STOR-i/Changepoints.jl"),
        Repo("https://github.com", "STOR-i/GaussianProcesses.jl"),
        Repo("https://github.com", "SciML/DifferentialEquations.jl"),
        Repo("https://github.com", "StatisticalRethinkingJulia/DynamicHMCModels.jl"),
        Repo("https://github.com", "StatisticalRethinkingJulia/StatisticalRethinking.jl"),
        Repo("https://github.com", "StatisticalRethinkingJulia/TuringModels.jl"),
        Repo("https://github.com", "TuringLang/AdvancedHMC.jl"),
        Repo("https://github.com", "TuringLang/Bijectors.jl"),
        Repo("https://github.com", "TuringLang/MCMCChains.jl"),
        Repo("https://github.com", "TuringLang/Turing.jl"),
        Repo("https://github.com", "Wikunia/ConstraintSolver.jl"),
        Repo("https://github.com", "Wikunia/Javis.jl"),
        Repo("https://github.com", "alan-turing-institute/MLJ.jl"),
        Repo("https://github.com", "alan-turing-institute/MLJBase.jl"),
        Repo("https://github.com", "alan-turing-institute/MLJModels.jl"),
        Repo("https://github.com", "alan-turing-institute/MLJTuning.jl"),
        Repo("https://github.com", "bcbi/PredictMD.jl"),
        Repo("https://github.com", "bcbi/SimpleContainerGenerator.jl"),
        Repo("https://github.com", "chriselrod/LoopVectorization.jl"),
        Repo("https://github.com", "cstjean/ScikitLearn.jl"),
        Repo("https://github.com", "denizyuret/AutoGrad.jl"),
        Repo("https://github.com", "diegozea/MIToS.jl"),
        Repo("https://github.com", "domluna/JuliaFormatter.jl"),
        Repo("https://github.com", "femtomc/Jaynes.jl"),
        Repo("https://github.com", "fonsp/Pluto.jl"),
        Repo("https://github.com", "fonsp/PlutoUI.jl"),
        Repo("https://github.com", "fonsp/PlutoUtils.jl"),
        Repo("https://github.com", "h-Klok/StatsWithJuliaBook"),
        Repo("https://github.com", "invenia/Impute.jl"),
        Repo("https://github.com", "invenia/PkgTemplates.jl"),
        Repo("https://github.com", "joshday/OnlineStats.jl"),
        Repo("https://github.com", "jrevels/Cassette.jl"),
        Repo("https://github.com", "julia-actions/MassInstallAction.jl"),
        Repo("https://github.com", "jump-dev/JuMP.jl"),
        Repo("https://github.com", "odow/SDDP.jl"),
        Repo("https://github.com", "probcomp/Gen.jl"),
        Repo("https://github.com", "queryverse/Query.jl"),
        Repo("https://github.com", "queryverse/VegaLite.jl"),
        Repo("https://github.com", "rikhuijzer/Codex.jl"),
        Repo("https://github.com", "timholy/ProfileView.jl"),
        Repo("https://github.com", "timholy/ProgressMeter.jl"),
        Repo("https://github.com", "timholy/Rebugger.jl"),
        Repo("https://github.com", "timholy/Revise.jl"),
        Repo("https://github.com", "timholy/SnoopCompile.jl"),
        Repo("https://github.com", "tlienart/Franklin.jl"),
        Repo("https://github.com", "tlienart/FranklinTemplates.jl"),
    ] :
    [
        Repo("https://github.com", "rikhuijzer/Codex.jl"),
    ]

function repository_ordering_is_valid()::Bool
    names = [r.name for r in repositories(; production=true)]
    sorted = Base.sort(names)
    unique_and_sorted = unique(sorted)
    ok = names == unique_and_sorted
    if !ok
        if length(names) != length(unique_and_sorted)
            error("repositories contains at least one duplicate")
        end
        for (actual, expected) in zip(names, unique_and_sorted)
            if actual != expected
                error("Repositories not ordered, expected: $expected, got: $actual")
            end
        end
    end
    ok
end

max_stars_repo_name: rikhuijzer/display-lint

max_issues_repo_name: rikhuijzer/display-lint

max_forks_repo_name: rikhuijzer/ShowLint