text:
"""
Single objective optimization methods accepted by `bboptimize()`.

The values are the method initialization routines or types derived from `Optimizer`.
"""
const SingleObjectiveMethods = ParamsDict(
    :random_search => random_search,
    :de_rand_1_bin => de_rand_1_bin,
    :de_rand_2_bin => de_rand_2_bin,
    :de_rand_1_bin_radiuslimited => de_rand_1_bin_radiuslimited,
    :de_rand_2_bin_radiuslimited => de_rand_2_bin_radiuslimited,
    :adaptive_de_rand_1_bin => adaptive_de_rand_1_bin,
    :adaptive_de_rand_1_bin_radiuslimited => adaptive_de_rand_1_bin_radiuslimited,
    :separable_nes => separable_nes,
    :xnes => xnes,
    :dxnes => dxnes,
    :resampling_memetic_search => resampling_memetic_searcher,
    :resampling_inheritance_memetic_search => resampling_inheritance_memetic_searcher,
    :simultaneous_perturbation_stochastic_approximation => SimultaneousPerturbationSA2,
    :generating_set_search => GeneratingSetSearcher,
    :probabilistic_descent => direct_search_probabilistic_descent,
    :ga => ga
)

const SingleObjectiveMethodNames = sort!(collect(keys(SingleObjectiveMethods)))

"""
Multi-objective optimization methods accepted by `bboptimize()`.

The values are the method initialization routines or types derived from `Optimizer`.
"""
const MultiObjectiveMethods = ParamsDict(
    :borg_moea => borg_moea
)

const MultiObjectiveMethodNames = sort!(collect(keys(MultiObjectiveMethods)))

"""
Names of optimization methods accepted by `bboptimize()`,
`:Method` keyword argument.
"""
const MethodNames = sort!(vcat(SingleObjectiveMethodNames,
                               MultiObjectiveMethodNames))

"""
Extend the list of valid methods by an Optimizer initializer method of your choice.
"""
add_method_to_bbo(id::Symbol, method::Function) = add_so_method_to_bbo(id, method)

function add_so_method_to_bbo(id::Symbol, method::Function)
   BlackBoxOptim.SingleObjectiveMethods[id] = method
   push!(BlackBoxOptim.SingleObjectiveMethodNames, id)
   push!(BlackBoxOptim.MethodNames, id)
end

function add_mo_method_to_bbo(id::Symbol, method::Function)
   BlackBoxOptim.MultiObjectiveMethods[id] = method
   push!(BlackBoxOptim.MultiObjectiveMethodNames, id)
   push!(BlackBoxOptim.MethodNames, id)
end


text:
# Solving linear systems failing.
using LinearAlgebra
using Printf
using Random
Random.seed!(0)
function hilbert(n::Integer)
  A = zeros(n,n)
  for j=1:n
    for i=1:n
      A[i,j] = 1/(i+j-1)
    end
  end
  return A
end
hilbert(5)
for k in [2,5,10,20,50,100,200]
  A = hilbert(k)
  b = randn(k)
  c = A\b
  #@show k, norm(A*c-b)/norm(b)
  @printf("%3i  %.4e\n", k, norm(A*c-b)/norm(b))
end

ext: jl


text:
using JSON, StanSample, Random, Statistics

stan_chris = "
data {
    int n_rows;
    int<lower=1> n_cols;
    matrix<lower=0>[n_rows,n_cols] x;
}

parameters {
   real mu;
}

model {
    mu ~ normal(0, 1);
}";

seed = 65445;
Random.seed!(seed)

n_rows = 10
n_cols = 2
x = fill(0, n_rows, n_cols)
data = Dict(:x => x, :n_rows => n_rows, :n_cols => n_cols)

tmpdir = joinpath(@__DIR__, "tmp")
sm = SampleModel("chris", stan_chris, tmpdir);
rc = stan_sample(sm; data, seed);

if success(rc)
	df = read_samples(sm , :dataframe)
    #df |> display
    [mean(df.mu), std(df.mu)] |> display
end


text:
using Documenter, Elsa

makedocs(sitename="Elsa.jl Documentation")


text:
const LQOI = LinQuadOptInterface
const MOI  = LQOI.MOI

mutable struct LinQuadSOS
    kind::Symbol
    weights::Vector{Float64}
    indices::Vector{Int}
end

mutable struct MockLinQuadModel # <: LinQuadOptInterface.LinQuadOptimizer

    sense::Symbol

    Qcon::Vector{Matrix{Float64}}
    A::Matrix{Float64}
    b::Vector{Float64}
    c::Vector{Float64}
    Qobj::Matrix{Float64}

    range::Vector{Float64} # constraint UB for range

    lb::Vector{Float64}
    ub::Vector{Float64}

    vartype::Vector{Cchar} # :Bin, :Int, :Con
    contype::Vector{Cchar} # :LEQ :GEQ, :EQ, :RANGE

    sos::Vector{LinQuadSOS}

    termination_status::MOI.TerminationStatusCode

    primal_status::MOI.ResultStatusCode

    dual_status::MOI.ResultStatusCode

    variable_primal_solution::Vector{Float64}
    variable_dual_solution::Vector{Float64}

    constraint_primal_solution::Vector{Float64}
    constraint_dual_solution::Vector{Float64}

    quadratic_primal_solution::Vector{Float64}
    quadratic_dual_solution::Vector{Float64}

    function MockLinQuadModel(env::Nothing,str::String="defaultname")
        m = new()

        m.sense = :minimize

        m.Qcon = Matrix{Float64}[]
        m.A = zeros(0,0)
        m.b = zeros(0)
        m.c = zeros(0)
        m.Qobj = zeros(0,0)

        m.range = zeros(0)

        m.lb = zeros(0)
        m.ub = zeros(0)

        m.vartype = Cchar[]
        m.contype = Cchar[]

        m.sos = LinQuadSOS[]

        m.termination_status = MOI.OPTIMIZE_NOT_CALLED
        m.primal_status = MOI.NO_SOLUTION
        m.dual_status = MOI.NO_SOLUTION

        m.variable_primal_solution = zeros(0)
        m.variable_dual_solution = zeros(0)

        m.constraint_primal_solution = zeros(0)
        m.constraint_dual_solution = zeros(0)

        m.quadratic_primal_solution = zeros(0)
        m.quadratic_dual_solution = zeros(0)

        return m
    end
end

function Base.show(io::IO, model::MockLinQuadModel)
    println(io, "MockLinQuadModel")
    println(io, "    Sense       $(model.sense)")
    println(io, "    Variables   $(length(model.lb))")
    println(io, "    Constraints $(length(model.b))")
    return
end

"""
Solution builder to create solutions for the mock solver.
Should be called inside `MOI.optimize!(model::LinQuadOptimizer)` right before changing signs. This means that these solutions replicate the low-level solver output.
The idea is to run the test with a solver like Xpress, Gurobi, GLPK or CPLEX to obtain the detailed solution.
"""
function print_low_level_solution(model)
    println()
    println("------------------------------------------")
    println("---------------- solution ----------------")
    println("------------------------------------------")
    println()
    println("---------------- statuses ----------------")
    println()
    @show model.termination_status
    @show model.primal_status
    @show model.dual_status
    println()
    println("----------------- primal -----------------")
    println()
    @show model.variable_primal_solution
    @show model.constraint_primal_solution
    @show model.qconstraint_primal_solution
    println()
    println("------------------ dual- -----------------")
    println()
    @show model.variable_dual_solution
    @show model.constraint_dual_solution
    @show model.qconstraint_dual_solution
    println()
    println("------------------------------------------")
    println()
end

num_vars(inner::MockLinQuadModel) = length(inner.c)
num_cons(inner::MockLinQuadModel) = length(inner.b)

const SUPPORTED_OBJECTIVES = [
    MOI.SingleVariable,
    LQOI.Linear,
    LQOI.Quad
]

const SUPPORTED_CONSTRAINTS = [
    (LQOI.Linear, LQOI.EQ),
    (LQOI.Linear, LQOI.LE),
    (LQOI.Linear, LQOI.GE),
    (Linear, IV),
    (LQOI.Quad, LQOI.EQ),
    (LQOI.Quad, LQOI.LE),
    (LQOI.Quad, LQOI.GE),
    (LQOI.SinVar, LQOI.EQ),
    (LQOI.SinVar, LQOI.LE),
    (LQOI.SinVar, LQOI.GE),
    (LQOI.SinVar, LQOI.IV),
    (LQOI.SinVar, MOI.ZeroOne),
    (LQOI.SinVar, MOI.Integer),
    (LQOI.SinVar, MOI.Semiinteger{Float64}),
    (LQOI.SinVar, MOI.Semicontinuous{Float64}),
    (LQOI.VecVar, LQOI.SOS1),
    (LQOI.VecVar, LQOI.SOS2),
    (LQOI.VecVar, MOI.Nonnegatives),
    (LQOI.VecVar, MOI.Nonpositives),
    (LQOI.VecVar, MOI.Zeros),
    (LQOI.VecLin, MOI.Nonnegatives),
    (LQOI.VecLin, MOI.Nonpositives),
    (LQOI.VecLin, MOI.Zeros)
]

mutable struct MockLinQuadOptimizer <: LQOI.LinQuadOptimizer
    LQOI.@LinQuadOptimizerBase
    params::Dict{String,Any}
    l_rows::Vector{Int}
    q_rows::Vector{Int}

    termination_status_stored::Vector{MOI.TerminationStatusCode}
    primal_status_stored::Vector{MOI.ResultStatusCode}
    dual_status_stored::Vector{MOI.ResultStatusCode}

    variable_primal_solution_stored::Vector{Vector{Float64}}
    variable_dual_solution_stored::Vector{Vector{Float64}}

    constraint_primal_solution_stored::Vector{Vector{Float64}}
    constraint_dual_solution_stored::Vector{Vector{Float64}}

    quadratic_primal_solution_stored::Vector{Vector{Float64}}
    quadratic_dual_solution_stored::Vector{Vector{Float64}}

    MockLinQuadOptimizer(::Nothing) = new()
end

LQOI.LinearQuadraticModel(::Type{MockLinQuadOptimizer},env::Nothing) = MockLinQuadModel(env,"defaultname")

function MockLinQuadOptimizer(;kwargs...)

    instance = MockLinQuadOptimizer(nothing)
    instance.params = Dict{String,Any}()
    instance.l_rows = Int[]
    instance.q_rows = Int[]

    instance.termination_status_stored = MOI.TerminationStatusCode[]
    instance.primal_status_stored = MOI.ResultStatusCode[]
    instance.dual_status_stored = MOI.ResultStatusCode[]

    instance.variable_primal_solution_stored = Vector{Float64}[]
    instance.variable_dual_solution_stored = Vector{Float64}[]

    instance.constraint_primal_solution_stored = Vector{Float64}[]
    instance.constraint_dual_solution_stored = Vector{Float64}[]

    instance.quadratic_primal_solution_stored = Vector{Float64}[]
    instance.quadratic_dual_solution_stored = Vector{Float64}[]

    MOI.empty!(instance)
    for (name, value) in kwargs
        instance.params[string(name)] = value
        setparam!(instance.inner, string(name), value)
    end
    return instance
end

"""
    unload(from::Vector, to, warn = true)

Helper function to remove the first element of a vector and return it.
If the vector is empty data in `default` is returned instead.
Used in `fakesolve`.
"""
function unload(from, default, warn = true)
    if !isempty(from)
        out = from[1]
        popfirst!(from)
        return out
    else
        if warn
            @warn("No data in the input vector, returning default.")
        end
        return default
    end
end

"""
    fakesolve(instance::MockLinQuadOptimizer)

Set solutions upon solve calls.
Data held in `MockLinQuadOptimizer` stored data is passed to the low-level emulator `MockLinQuadModel`.
"""
function fakesolve(instance::MockLinQuadOptimizer)

    instance.inner.termination_status = unload(instance.termination_status_stored, instance.inner.termination_status)
    instance.inner.primal_status = unload(instance.primal_status_stored, instance.inner.primal_status)
    instance.inner.dual_status = unload(instance.dual_status_stored, instance.inner.dual_status)

    instance.inner.variable_primal_solution = unload(instance.variable_primal_solution_stored, instance.inner.variable_primal_solution)
    instance.inner.variable_dual_solution = unload(instance.variable_dual_solution_stored, instance.inner.variable_dual_solution)

    instance.inner.constraint_primal_solution = unload(instance.constraint_primal_solution_stored, instance.inner.constraint_primal_solution)
    instance.inner.constraint_dual_solution = unload(instance.constraint_dual_solution_stored, instance.inner.constraint_dual_solution)

    instance.inner.quadratic_primal_solution = unload(instance.quadratic_primal_solution_stored, instance.inner.quadratic_primal_solution)
    instance.inner.quadratic_dual_solution = unload(instance.quadratic_dual_solution_stored, instance.inner.quadratic_dual_solution)

    return
end

function set_variable_primal_solution!(instance::MockLinQuadOptimizer, input)
    push!(instance.variable_primal_solution_stored, input)
end
function set_variable_dual_solution!(instance::MockLinQuadOptimizer, input)
    push!(instance.variable_dual_solution_stored, input)
end
function set_constraint_primal_solution!(instance::MockLinQuadOptimizer, input)
    push!(instance.constraint_primal_solution_stored, input)
end
function set_constraint_dual_solution!(instance::MockLinQuadOptimizer, input)
    push!(instance.constraint_dual_solution_stored, input)
end
function set_quadratic_dual_solution!(instance::MockLinQuadOptimizer, input)
    push!(instance.quadratic_dual_solution_stored, input)
end
function set_quadratic_primal_solution!(instance::MockLinQuadOptimizer, input)
    push!(instance.quadratic_primal_solution_stored, input)
end
function set_termination_status!(instance::MockLinQuadOptimizer, input)
    push!(instance.termination_status_stored, input)
end
function set_primal_status!(instance::MockLinQuadOptimizer, input)
    push!(instance.primal_status_stored, input)
end
function set_dual_status!(instance::MockLinQuadOptimizer, input)
    push!(instance.dual_status_stored, input)
end

function set_solution!(instance::MockLinQuadOptimizer;
    variable_primal = Float64[],
    variable_dual = Float64[],
    constraint_primal = Float64[],
    constraint_dual = Float64[],
    quadratic_primal = Float64[],
    quadratic_dual = Float64[],
    termination_status = MOI.OPTIMAL,
    primal_status = MOI.FEASIBLE_POINT,
    dual_status = MOI.FEASIBLE_POINT
    )

    set_variable_primal_solution!(instance, variable_primal)
    set_variable_dual_solution!(instance, variable_dual)
    set_constraint_primal_solution!(instance, constraint_primal)
    set_constraint_dual_solution!(instance, constraint_dual)
    set_quadratic_primal_solution!(instance, quadratic_primal)
    set_quadratic_dual_solution!(instance, quadratic_dual)
    set_termination_status!(instance, termination_status)
    set_primal_status!(instance, primal_status)
    set_dual_status!(instance, dual_status)

    return
end

LQOI.get_number_linear_constraints(instance::MockLinQuadOptimizer) = num_cons(instance.inner) - LQOI.get_number_quadratic_constraints(instance)
function LQOI.get_number_quadratic_constraints(instance::MockLinQuadOptimizer)
    c = 0
    for i in 1:num_cons(instance.inner)
        if !isempty(instance.inner.Qcon[i])
            c += 1
        end
    end
    return c
end

function MOI.empty!(instance::MockLinQuadOptimizer)
    MOI.empty!(instance, nothing)
    # do not empty param
    instance.l_rows = Int[]
    instance.q_rows = Int[]
    for (name, value) in instance.params
        setparam!(instance.inner, name, value)
    end
end

LQOI.supported_constraints(s::MockLinQuadOptimizer) = SUPPORTED_CONSTRAINTS
LQOI.supported_objectives(s::MockLinQuadOptimizer) = SUPPORTED_OBJECTIVES

cintvec(v::Vector) = convert(Vector{Int32}, v)

backend_type(m::MockLinQuadOptimizer, ::MOI.GreaterThan{T}) where T = Cchar('G')
backend_type(m::MockLinQuadOptimizer, ::MOI.LessThan{T}) where T    = Cchar('L')
backend_type(m::MockLinQuadOptimizer, ::MOI.EqualTo{T}) where T     = Cchar('E')
# Implemented separately
# backend_type(m::MockLinQuadOptimizer, ::MOI.Interval{T}) where T    = Cchar('R')

backend_type(m::MockLinQuadOptimizer, ::MOI.Zeros)        = Cchar('E')
backend_type(m::MockLinQuadOptimizer, ::MOI.Nonpositives) = Cchar('L')
backend_type(m::MockLinQuadOptimizer, ::MOI.Nonnegatives) = Cchar('G')

backend_type(m::MockLinQuadOptimizer, ::Val{:Continuous}) = Cchar('C')
backend_type(m::MockLinQuadOptimizer, ::Val{:Upperbound}) = Cchar('U')
backend_type(m::MockLinQuadOptimizer, ::Val{:Lowerbound}) = Cchar('L')

function LQOI.change_variable_bounds!(instance::MockLinQuadOptimizer, colvec, valvec, sensevec)

    lb_len = count(x->x==Cchar('L'), sensevec)
    LB_val = Array{Float64}(undef, 0)
    sizehint!(LB_val, lb_len)
    LB_col = Array{Cint}(undef, 0)
    sizehint!(LB_col, lb_len)

    ub_len = count(x->x==Cchar('U'), sensevec)
    UB_val = Array{Float64}(undef, 0)
    sizehint!(UB_val, ub_len)
    UB_col = Array{Cint}(undef, 0)
    sizehint!(UB_col, ub_len)

    if lb_len + ub_len != length(sensevec)
        error("Invalid values for sensevec")
    end

    for i in eachindex(valvec)
        if sensevec[i] == Cchar('L')
            push!(LB_col, colvec[i])
            push!(LB_val, valvec[i])
        elseif sensevec[i] == Cchar('U')
            push!(UB_col, colvec[i])
            push!(UB_val, valvec[i])
        end
    end

    if lb_len > 0
        for i in eachindex(LB_col)
            instance.inner.lb[LB_col[i]] = LB_val[i]
        end
    end

    if ub_len > 0
        for i in eachindex(UB_col)
            instance.inner.ub[UB_col[i]] = UB_val[i]
        end
    end
end

function LQOI.get_variable_lowerbound(instance::MockLinQuadOptimizer, col)
    instance.inner.lb[col]
end

function LQOI.get_variable_upperbound(instance::MockLinQuadOptimizer, col)
    instance.inner.ub[col]
end

function LQOI.add_linear_constraints!(instance::MockLinQuadOptimizer, A::CSRMatrix{Float64}, sensevec, rhsvec)

    newrows = length(rhsvec)
    rows = num_cons(instance.inner)
    addedrows = collect((rows+1):(rows+newrows))
    # quadind
    append!(instance.l_rows,addedrows)

    rowvec, colvec, coefvec = row_pointers(A), colvals(A), row_nonzeros(A)

    rows = length(rhsvec)
    cols = size(instance.inner.A)[2]

    An = Array(SparseMatrixCSC(cols,rows,rowvec,colvec,coefvec)')

    instance.inner.A = vcat(instance.inner.A,An)

    append!(instance.inner.b,rhsvec)
    append!(instance.inner.contype,sensevec)

    append!(instance.inner.range,[Inf for i in 1:rows])
    append!(instance.inner.Qcon,[zeros(0,0) for i in 1:rows])

    return
end

function LQOI.add_ranged_constraints!(instance::MockLinQuadOptimizer, A::CSRMatrix{Float64}, lowerbound, upperbound)

    newrows = length(lowerbound)
    rows = num_cons(instance.inner)
    addedrows = collect((rows+1):(rows+newrows))
    # quadind
    append!(instance.l_rows,addedrows)

    rowvec, colvec, coefvec = row_pointers(A), colvals(A), row_nonzeros(A)
    rows = length(lowerbound)
    cols = size(instance.inner.A)[2]

    An = Array(SparseMatrixCSC(cols,rows,rowvec,colvec,coefvec)')

    instance.inner.A = vcat(instance.inner.A,An)

    append!(instance.inner.b,lowerbound)
    append!(instance.inner.contype,['R' for i in 1:rows])

    append!(instance.inner.range,upperbound)
    append!(instance.inner.Qcon,[zeros(0,0) for i in 1:rows])
    return
end

function modify_ranged_constraints!(instance::MockLinQuadOptimizer, rows, lowerbound, upperbound)
    # quadind
    _rows = instance.l_rows[rows]
    for i in _rows
        instance.inner.b[i] = lowerbound[i]
        instance.inner.range[i] = upperbound[i]
    end
end

function LQOI.get_rhs(instance::MockLinQuadOptimizer, row)
    # quadind
    _row = instance.l_rows[row]
    return instance.inner.b[_row]
end
function LQOI.get_quadratic_rhs(instance::MockLinQuadOptimizer, row)
    # quadind
    _row = instance.q_rows[row]
    return instance.inner.b[_row]
end

function LQOI.get_range(instance::MockLinQuadOptimizer, row)
    # quadind
    _row = instance.l_rows[row]
    return instance.inner.b[_row], instance.inner.range[_row]
end

function LQOI.get_linear_constraint(instance::MockLinQuadOptimizer, row)
    # quadind
    _row = instance.l_rows[row]

    vals = instance.inner.A[_row,:]

    outvals = Float64[]
    outinds = Int[]
    for i in eachindex(vals)
        if abs(vals[i]) > 0.0
            push!(outvals,vals[i])
            push!(outinds,i)
        end
    end
    return outinds, outvals
end

function LQOI.get_quadratic_constraint(instance::MockLinQuadOptimizer, row)
    # quadind
    _row = instance.q_rows[row]

    vals = instance.inner.A[_row,:]

    outvals = Float64[]
    outinds = Int[]
    for i in eachindex(vals)
        if abs(vals[i]) > 0.0
            push!(outvals,vals[i])
            push!(outinds,i)
        end
    end

    Q = instance.inner.Qcon[_row]

    #TODO (@joaquim) fix here
    return outinds, outvals, sparse(0.5*Q)
end

function LQOI.change_matrix_coefficient!(instance::MockLinQuadOptimizer, row, col, coef)
    # quadind
    _row = instance.l_rows[row]
    instance.inner.A[_row,col] = coef
end
function LQOI.change_rhs_coefficient!(instance::MockLinQuadOptimizer, row, coef)
    # quadind
    _row = instance.l_rows[row]
    instance.inner.b[_row] = coef
end
function LQOI.change_objective_coefficient!(instance::MockLinQuadOptimizer, col, coef)
    instance.inner.c[col] = coef
end
function LQOI.delete_linear_constraints!(instance::MockLinQuadOptimizer, rowbeg, rowend)
    _rows = instance.l_rows[collect(rowbeg:rowend)]
    survive = setdiff(collect(1:num_cons(instance.inner)), _rows)
    instance.inner.A = instance.inner.A[survive,:]
    instance.inner.b = instance.inner.b[survive]
    instance.inner.contype = instance.inner.contype[survive]
    instance.inner.range = instance.inner.range[survive]
    instance.inner.Qcon = instance.inner.Qcon[survive]
    for i in rowend:-1:rowbeg
        deleteat!(instance.l_rows,i)
    end
end

function LQOI.delete_quadratic_constraints!(instance::MockLinQuadOptimizer, rowbeg, rowend)
    _rows = instance.q_rows[collect(rowbeg:rowend)]
    survive = setdiff(collect(1:num_cons(instance.inner)), _rows)
    instance.inner.A = instance.inner.A[survive,:]
    instance.inner.b = instance.inner.b[survive]
    instance.inner.contype = instance.inner.contype[survive]
    instance.inner.range = instance.inner.range[survive]
    instance.inner.Qcon = instance.inner.Qcon[survive]
    for i in rowend:-1:rowbeg
        deleteat!(instance.q_rows,i)
    end
end

function LQOI.change_variable_types!(instance::MockLinQuadOptimizer, colvec, typevec)
    for i in eachindex(colvec)
        instance.inner.vartype[colvec[i]] = typevec[i]
    end
end

function sensetype(::MockLinQuadOptimizer, typeval)
    if typeval == 'G'
        return 'G'
    elseif typeval == 'E'
        return 'E'
    elseif typeval == 'L'
        return 'L'
    else
        return 'R'
    end
end
function LQOI.change_linear_constraint_sense!(instance::MockLinQuadOptimizer, rowvec, sensevec)
    _rows = instance.l_rows[rowvec]
    for i in eachindex(_rows)
        instance.inner.vartype[_rows[i]] = sensetype(instance, sensevec[i])
    end
end

function LQOI.add_sos_constraint!(instance::MockLinQuadOptimizer, colvec, valvec, typ)
    sos = LinQuadSOS(typ, valvec, colvec)
    push!(instance.inner.sos,sos)
end
function LQOI.delete_sos!(instance::MockLinQuadOptimizer, idx1, idx2)
    delete_between(instance.inner.sos, idx1, idx2)
end
function LQOI.get_sos_constraint(instance::MockLinQuadOptimizer, idx)
    sos = instance.inner.sos[idx]
    return sos.indices, sos.weights, sos.kind
end

function LQOI.add_quadratic_constraint!(instance::MockLinQuadOptimizer, cols, coefs, rhs, sense, I, J, V)
    @assert length(I) == length(J) == length(V)

    nvars = length(instance.inner.c)
    Q = Array(sparse(I,J,V,nvars,nvars))

    a = zeros(nvars)
    for i in eachindex(cols)
        a[cols[i]] = coefs[i]
    end

    instance.inner.A = vcat(instance.inner.A,a')
    push!(instance.inner.b,rhs)
    push!(instance.inner.contype,sense)
    push!(instance.inner.range,Inf)
    push!(instance.inner.Qcon,Q)

    # scalediagonal!(V, I, J, 0.5)
    # scalediagonal!(V, I, J, 2.0)
    push!(instance.q_rows, num_cons(instance.inner))
end

#=
    Objective
=#

function LQOI.set_quadratic_objective!(instance::MockLinQuadOptimizer, I, J, V)
    @assert length(I) == length(J) == length(V)
    n = num_vars(instance.inner)
    Q = Array(sparse(I,J,V,n,n))
    # scalediagonal!(V, I, J, 0.5)
    instance.inner.Qobj = Q
    # scalediagonal!(V, I, J, 2.0)
    return
end

function LQOI.set_linear_objective!(instance::MockLinQuadOptimizer, colvec, coefvec)
    nvars = num_vars(instance.inner)
    obj = zeros(Float64, nvars)

    for i in eachindex(colvec)
        obj[colvec[i]] = coefvec[i]
    end

    instance.inner.c = obj
    return
end

function LQOI.change_objective_sense!(instance::MockLinQuadOptimizer, symbol)
    if symbol == :min
        instance.inner.sense = :minimize
    else
        instance.inner.sense = :maximize
    end
end

function LQOI.get_linear_objective!(instance::MockLinQuadOptimizer, x)
    for i in eachindex(x)
        x[i] = instance.inner.c[i]
    end
end

function LQOI.get_quadratic_terms_objective(instance::MockLinQuadOptimizer)
    I = Int32[]
    J = Int32[]
    V = Float64[]
    Q = instance.inner.Qobj
    n, m = size(Q)
    for i in 1:n, j in 1:n
        if Q[i,j] != 0
            push!(I,i)
            push!(J,j)
            push!(V,Q[i,j])
        end
    end
    return sparse(Q)
end

function LQOI.get_objectivesense(instance::MockLinQuadOptimizer)
    s = instance.inner.sense
    if s == :maximize
        return MOI.MAX_SENSE
    else
        return MOI.MIN_SENSE
    end
end

#=
    Variables
=#

LQOI.get_number_variables(instance::MockLinQuadOptimizer) = length(instance.inner.c)

function LQOI.add_variables!(instance::MockLinQuadOptimizer, int)
    append!(instance.inner.ub,Inf*ones(int))
    append!(instance.inner.lb,-Inf*ones(int))
    append!(instance.inner.c,0.0*ones(int))
    append!(instance.inner.vartype,['C' for i in 1:int])
    instance.inner.A = hcat(instance.inner.A,zeros(length(instance.inner.b),int))
end

function LQOI.delete_variables!(instance::MockLinQuadOptimizer, colbeg, colend)
    instance.inner.Qobj = delete_colrow(instance.inner.Qobj, colbeg, colend)
    instance.inner.Qcon = map(x->delete_colrow(x, colbeg, colend), instance.inner.Qcon)
    if colbeg > 1 && colend < length(instance.inner.lb)
        instance.inner.A = hcat(instance.inner.A[:,1:colbeg-1],instance.inner.A[:,colend+1:end])
        instance.inner.lb = vcat(instance.inner.lb[1:colbeg-1],instance.inner.lb[colend+1:end])
        instance.inner.ub = vcat(instance.inner.ub[1:colbeg-1],instance.inner.ub[colend+1:end])
        instance.inner.c = vcat(instance.inner.c[1:colbeg-1],instance.inner.c[colend+1:end])
        instance.inner.vartype = vcat(instance.inner.vartype[1:colbeg-1],instance.inner.vartype[colend+1:end])
    elseif colbeg > 1
        instance.inner.A = instance.inner.A[:,1:colbeg-1]
        instance.inner.lb = instance.inner.lb[1:colbeg-1]
        instance.inner.ub = instance.inner.ub[1:colbeg-1]
        instance.inner.c = instance.inner.c[1:colbeg-1]
        instance.inner.vartype = instance.inner.vartype[1:colbeg-1]
    elseif colend < length(instance.inner.lb)
        instance.inner.A = instance.inner.A[:,colend+1:end]
        instance.inner.lb = instance.inner.lb[colend+1:end]
        instance.inner.ub = instance.inner.ub[colend+1:end]
        instance.inner.c = instance.inner.c[colend+1:end]
        instance.inner.vartype = instance.inner.vartype[colend+1:end]
    else
        instance.inner.A = zeros(length(instance.inner.b),0)
        instance.inner.lb = Vector{Float64}[]
        instance.inner.ub = Vector{Float64}[]
        instance.inner.c = Vector{Float64}[]
        instance.inner.vartype = Cchar[]
    end
end

function delete_colrow(Q, colbeg, colend)
    n, m = size(Q)
    @assert n == m

    if colbeg > n
        # do nothing
        return Q
    elseif colbeg > 1 && colend < n
        Q = hcat(Q[:,1:colbeg-1], Q[:,colend+1:end])
        Q = vcat(Q[1:colbeg-1,:], Q[colend+1:end,:])
        return Q
    elseif colbeg > 1
        return Q[1:colbeg-1, 1:colbeg-1]
    elseif colend < n
        return Q[colend+1:end, colend+1:end]
    else
        return zeros(0,0)
    end
end

function delete_between(V, colbeg, colend)
    n = length(V)
    if colbeg > n
        # do nothing
        return V
    elseif colbeg > 1 && colend < n
        V = vcat(V[1:colbeg-1], V[colend+1:end])
        return V
    elseif colbeg > 1
        return V[1:colbeg-1]
    elseif colend < n
        return V[colend+1:end]
    else
        return zeros(0)
    end
end

#=
    Solve
=#

LQOI.solve_mip_problem!(instance::MockLinQuadOptimizer) = fakesolve(instance)

LQOI.solve_quadratic_problem!(instance::MockLinQuadOptimizer) = fakesolve(instance)

LQOI.solve_linear_problem!(instance::MockLinQuadOptimizer) = fakesolve(instance)

function LQOI.get_termination_status(instance::MockLinQuadOptimizer)
    return instance.inner.termination_status
end

function LQOI.get_primal_status(instance::MockLinQuadOptimizer)
    return instance.inner.primal_status
end

function LQOI.get_dual_status(instance::MockLinQuadOptimizer)
    return instance.inner.dual_status
end

function LQOI.get_variable_primal_solution!(instance::MockLinQuadOptimizer, place)
    for i in eachindex(place)
        place[i] = instance.inner.variable_primal_solution[i]
    end
end

function LQOI.get_linear_primal_solution!(instance::MockLinQuadOptimizer, place)
    for i in eachindex(place)
        place[i] = instance.inner.constraint_primal_solution[i]
    end
end

function LQOI.get_quadratic_primal_solution!(instance::MockLinQuadOptimizer, place)
    for i in eachindex(place)
        place[i] = instance.inner.quadratic_primal_solution[i]
    end
end

function LQOI.get_variable_dual_solution!(instance::MockLinQuadOptimizer, place)
    for i in eachindex(place)
        place[i] = instance.inner.variable_dual_solution[i]
    end
end

function LQOI.get_linear_dual_solution!(instance::MockLinQuadOptimizer, place)
    for i in eachindex(place)
        place[i] = instance.inner.constraint_dual_solution[i]
    end
end

function LQOI.get_quadratic_dual_solution!(instance::MockLinQuadOptimizer, place)
    for i in eachindex(place)
        place[i] = instance.inner.quadratic_dual_solution[i]
    end
end

function get_objval(inner::MockLinQuadModel)
    x = inner.variable_primal_solution
    obj = 0.0
    obj += inner.c' * x
    if !isempty(inner.Qobj)
        Q = Matrix(Symmetric(inner.Qobj, :U))
        obj += (0.5) * x' * Q * x
    end
    return obj
end

LQOI.get_objective_value(instance::MockLinQuadOptimizer) = get_objval(instance.inner)
LQOI.get_objective_bound(instance::MockLinQuadOptimizer) = get_objval(instance.inner)
LQOI.get_relative_mip_gap(instance::MockLinQuadOptimizer) = 0.0
LQOI.get_iteration_count(instance::MockLinQuadOptimizer) = 1
LQOI.get_barrier_iterations(instance::MockLinQuadOptimizer) = 1
LQOI.get_node_count(instance::MockLinQuadOptimizer) = 1

function LQOI.get_farkas_dual!(instance::MockLinQuadOptimizer, place)
    for i in eachindex(place)
        place[i] = instance.inner.constraint_dual_solution[i]
    end
end

function LQOI.get_farkas_dual_bounds!(instance::MockLinQuadOptimizer, place)
    for i in eachindex(place)
        place[i] = instance.inner.variable_dual_solution[i]
    end
end

function hasdualray(instance::MockLinQuadOptimizer)
    return !(NaN in instance.inner.constraint_dual_solution)
end

function LQOI.get_unbounded_ray!(instance::MockLinQuadOptimizer, place)
    for i in eachindex(place)
        place[i] = instance.inner.variable_primal_solution[i]
    end
end

function hasprimalray(instance::MockLinQuadOptimizer)
    return !(NaN in instance.inner.variable_primal_solution)
end

#=
LQOI.get_objective_bound(instance::MockLinQuadOptimizer) = get_objval(instance.inner)

function LQOI.get_relative_mip_gap(instance::MockLinQuadOptimizer)
    L = get_objval(instance.inner)
    U = get_objbound(instance.inner)
    return abs(U-L)/U
end

LQOI.get_iteration_count(instance::MockLinQuadOptimizer)  = get_iter_count(instance.inner)

LQOI.get_barrier_iterations(instance::MockLinQuadOptimizer) = get_barrier_iter_count(instance.inner)

LQOI.get_node_count(instance::MockLinQuadOptimizer) = get_node_count(instance.inner)
=#
#=
function LQOI.add_mip_starts!(instance::MockLinQuadOptimizer, colvec::Vector{Int}, valvec::Vector)
    x = zeros(num_vars(instance.inner))
    for (col, val) in zip(colvec, valvec)
        x[col] = val
    end
    loadbasis(instance.inner, x)
end
=#


text:
export dot_zero,
       remove_duplicates_sorted!,
       samedir,
       ismultiple,
       nonzero_indices,
       right_turn,
       is_cyclic_permutation,
       is_right_turn,
       to_negative_vector,
       _above,
       _dr,
       _up,
       distance,
       append_zeros,
       prepend_zeros

"""
    dot_zero(x::AbstractVector{N}, y::AbstractVector{N}) where{N<:Real}

Dot product with preference for zero value in the presence of infinity values.

### Input

- `x` -- first vector
- `y` -- second vector

### Output

The dot product of `x` and `y`, but with the rule that `0 * Inf == 0`.
"""
function dot_zero(x::AbstractVector{N}, y::AbstractVector{N}) where{N<:Real}
    res = zero(N)
    for i in 1:length(x)
        if !iszero(x[i]) && !iszero(y[i])
            res += x[i] * y[i]
        end
    end
    return res
end

"""
    remove_duplicates_sorted!(v::AbstractVector)

Remove duplicate entries in a sorted vector.

### Input

- `v` -- sorted vector

### Output

The input vector without duplicates.
"""
function remove_duplicates_sorted!(v::AbstractVector)
    for i in length(v)-1:-1:1
        if v[i] == v[i+1]
            splice!(v, i+1)
        end
    end
    return v
end

"""
    samedir(u::AbstractVector{<:Real}, v::AbstractVector{<:Real})

Check whether two vectors point in the same direction.

### Input

- `u` -- first vector
- `v` -- second vector

### Output

`(true, k)` iff the vectors are identical up to a positive scaling factor `k`
such that `u = k * v`, and `(false, 0)` otherwise.

### Examples

```jldoctest
julia> using LazySets: samedir

julia> samedir([1, 2, 3], [2, 4, 6])
(true, 0.5)

julia> samedir([1, 2, 3], [3, 2, 1])
(false, 0)

julia> samedir([1, 2, 3], [-1, -2, -3])
(false, 0)

```
"""
function samedir(u::AbstractVector{<:Real}, v::AbstractVector{<:Real})
    return _ismultiple(u, v; allow_negative=false)
end

"""
    ismultiple(u::AbstractVector{<:Real}, v::AbstractVector{<:Real})

Check whether two vectors are linearly dependent.

### Input

- `u` -- first vector
- `v` -- second vector

### Output

`(true, k)` iff the vectors are identical up to a scaling factor `k ≠ 0` such
that `u = k * v`, and `(false, 0)` otherwise.

### Examples

```jldoctest
julia> using LazySets: ismultiple

julia> ismultiple([1, 2, 3], [2, 4, 6])
(true, 0.5)

julia> ismultiple([1, 2, 3], [3, 2, 1])
(false, 0)

julia> ismultiple([1, 2, 3], [-1, -2, -3])
(true, -1.0)

```
"""
function ismultiple(u::AbstractVector{<:Real}, v::AbstractVector{<:Real})
    return _ismultiple(u, v; allow_negative=true)
end

function _ismultiple(u::AbstractVector, v::AbstractVector; allow_negative::Bool)
    @assert length(u) == length(v) "wrong dimension"
    no_factor = true
    factor = 0
    @inbounds for i in 1:length(u)
        if isapproxzero(u[i])
            if !isapproxzero(v[i])
                return (false, 0)
            end
            continue
        elseif isapproxzero(v[i])
            return (false, 0)
        end
        if no_factor
            no_factor = false
            factor = u[i] / v[i]
            if !allow_negative && factor < 0
                return (false, 0)
            end
        elseif !_isapprox(factor, u[i] / v[i])
            return (false, 0)
        end
    end
    if no_factor
        # both vectors are zero
        return (true, 0)
    end
    return (true, factor)
end

"""
    nonzero_indices(v::AbstractVector{N}) where {N<:Real}

Return the indices in which a vector is non-zero.

### Input

- `v` -- vector

### Output

A vector of ascending indices `i` such that the vector is non-zero in dimension
`i`.
"""
function nonzero_indices(v::AbstractVector{N}) where {N<:Real}
    n = length(v)
    res = Vector{Int}()
    sizehint!(res, n)
    for i in 1:n
        if v[i] != zero(N)
            push!(res, i)
        end
    end
    return res
end

function nonzero_indices(v::SparseVector{N}) where {N<:Real}
    return v.nzind
end

"""
    is_cyclic_permutation(candidate::AbstractVector, paragon::AbstractVector)

Checks if the elements in `candidate` are a cyclic permutation of the elements
in `paragon`.

### Input

- `candidate` -- candidate vector
- `paragon`   -- paragon vector

### Output

A boolean indicating if the elements of `candidate` are in the same order as in
`paragon` or any of its cyclic permutations.
"""
function is_cyclic_permutation(candidate::AbstractVector,
                               paragon::AbstractVector)
    m = length(candidate)
    if length(paragon) != m
        return false
    end
    return any(candidate == circshift(paragon, i) for i in 0:m-1)
end

"""
    _up(u::AbstractVector, v::AbstractVector)

Checks if the given vector is pointing towards the given direction.

### Input

- `u` -- direction
- `v` -- vector

### Output

A boolean indicating if the vector is pointing towards the direction.
"""
@inline function _up(u::AbstractVector, v::AbstractVector)
    dot(u, v) > 0
end

"""
    _dr(u::AbstractVector, Vi::AbstractVector, Vj::AbstractVector)

Returns the direction of the difference of the given vectors.

### Input

- `u` -- direction
- `Vi` -- first vector
- `Vj` -- second vector

### Output

A number indicating the direction of the difference of the given vectors.
"""
@inline function _dr(u::AbstractVector, Vi::AbstractVector, Vj::AbstractVector)
    dot(u, (Vi) - (Vj))
end

"""
    _above(u::AbstractVector, Vi::AbstractVector, Vj::AbstractVector)

Checks if the difference of the given vectors is pointing towards the given
direction.

### Input

- `u` -- direction
- `Vi` -- first vector
- `Vj` -- second vector

### Output

A boolean indicating if the difference of the given vectors is pointing
towards the given direction.
"""
@inline function _above(u::AbstractVector, Vi::AbstractVector, Vj::AbstractVector)
    _dr(u, Vi, Vj) > 0
end

"""
    to_negative_vector(v::AbstractVector{N}) where {N}

Negate a vector and convert to type `Vector`.

### Input

- `v` -- vector

### Output

A `Vector` equivalent to ``-v``.
"""
@inline function to_negative_vector(v::AbstractVector{N}) where {N}
    u = zeros(N, length(v))
    @inbounds for (i, vi) in enumerate(v)
        u[i] = -vi
    end
    return u
end

@inline function to_negative_vector(v::Vector)
    return -v
end

@inline function to_negative_vector(v::SparseVector{N}) where {N}
    u = zeros(N, length(v))
    @inbounds for (ni, i) in enumerate(v.nzind)
        u[i] = -v.nzval[ni]
    end
    return u
end

"""
    right_turn([O::AbstractVector{N}=[0, 0]], u::AbstractVector{N},
               v::AbstractVector{N}) where {N<:Real}

Compute a scalar that determines whether the acute angle defined by three 2D
points `O`, `u`, `v` in the plane is a right turn (< 180° counter-clockwise)
with respect to the center `O`.

### Input

- `O` -- (optional; default: `[0, 0]`) 2D center point
- `u` -- first 2D point
- `v` -- second 2D point

### Output

A scalar representing the rotation.
If the result is 0, the points are collinear; if it is positive, the points
constitute a positive angle of rotation around `O` from `u` to `v`; otherwise
they constitute a negative angle.

### Algorithm

The [cross product](https://en.wikipedia.org/wiki/Cross_product) is used to
determine the sense of rotation.
"""
@inline function right_turn(O::AbstractVector{N},
                            u::AbstractVector{N},
                            v::AbstractVector{N}) where {N<:Real}
    return (u[1] - O[1]) * (v[2] - O[2]) - (u[2] - O[2]) * (v[1] - O[1])
end

# version for O = origin
@inline function right_turn(u::AbstractVector{N},
                            v::AbstractVector{N}) where {N<:Real}
    return u[1] * v[2] - u[2] * v[1]
end

"""
    is_right_turn([O::AbstractVector{N}=[0, 0]], u::AbstractVector{N},
                  v::AbstractVector{N}) where {N<:Real}

Determine whether the acute angle defined by three 2D points `O`, `u`, `v`
in the plane is a right turn (< 180° counter-clockwise) with
respect to the center `O`.
Determine if the acute angle defined by two 2D vectors is a right turn (< 180°
counter-clockwise) with respect to the center `O`.

### Input

- `O` -- (optional; default: `[0, 0]`) 2D center point
- `u` -- first 2D direction
- `v` -- second 2D direction

### Output

`true` iff the vectors constitute a right turn.
"""
@inline function is_right_turn(O::AbstractVector{N},
                               u::AbstractVector{N},
                               v::AbstractVector{N}) where {N<:Real}
    return _geq(right_turn(O, u, v), zero(N))
end

# version for O = origin
@inline function is_right_turn(u::AbstractVector{N},
                               v::AbstractVector{N}) where {N<:Real}
    return _geq(right_turn(u, v), zero(N))
end

"""
    distance(x::AbstractVector, y::AbstractVector; [p]::Real=2.0)

Compute the distance between two vectors with respect to the given `p`-norm,
computed as

```math
    \\|x - y\\|_p = \\left( \\sum_{i=1}^n | x_i - y_i |^p \\right)^{1/p}
```

### Input

- `x` -- vector
- `y` -- vector
- `p` -- (optional, default: `2.0`) the `p`-norm used; `p = 2.0` corresponds to
         the usual Euclidean norm

### Output

A scalar representing ``‖ x - y ‖_p``.
"""
function distance(x::AbstractVector, y::AbstractVector; p::Real=2.0)
    return norm(x - y, p)
end

"""
    allequal(x)

Check whether all elements in a sequence are equal

### Input

- `x` -- sequence

### Output

`true` iff all elements in `x` are equal.

### Notes

The code is taken from [here](https://stackoverflow.com/a/47578613).
"""
function allequal(x)
    length(x) < 2 && return true
    e1 = @inbounds x[1]
    i = 2
    @inbounds for i=2:length(x)
        x[i] == e1 || return false
    end
    return true
end

# if `vector` has exactly one non-zero entry, return its index
# otherwise return 0
function find_unique_nonzero_entry(vector::AbstractVector{N}) where {N}
    res = 0
    for (i, v) in enumerate(vector)
        if v != zero(N)
            if res != 0
                # at least two non-zero entries
                return 0
            else
                # first non-zero entry so far
                res = i
            end
        end
    end
    return res
end

function append_zeros(v::AbstractVector{N}, n::Int) where {N}
    return vcat(v, zeros(N, n))
end

function append_zeros(v::SparseVector{N}, n::Int) where {N}
    return sparsevec(v.nzind, v.nzval, v.n + n)
end

function prepend_zeros(v::AbstractVector{N}, n::Int) where {N}
    return vcat(zeros(N, n), v)
end

function prepend_zeros(v::SparseVector{N}, n::Int) where {N}
    return sparsevec(v.nzind .+ n, v.nzval, v.n + n)
end


text:
using FuzzySets, Test

step_size = 0.005
levels = collect(0:step_size:1)

A₁ = FuzzyNumber(levels, number=1)
A₂ = FuzzyNumber(levels, number=2)
B₁ = FuzzyNumber(levels, number=0)
B₂ = FuzzyNumber(levels, number=0)

A⃗ = FuzzyVector([A₁, A₂])
@test length(A⃗) == 2
@test A⃗[1] == A₁
@test A⃗[2] == A₂
@test iterate(A⃗, 1) == A₁
@test iterate(A⃗, 2) == A₂
@test isnothing(iterate(A⃗, 3))

B⃗ = FuzzyVector([B₁])
@test length(B⃗) == 1
@test B⃗[1] == B₁
B⃗ = B⃗ ∪ [B₂]
@test length(B⃗) == 2
@test B⃗[1] == B₁
@test B⃗[2] == B₂

@test A⃗ == A⃗
@test A⃗ == FuzzyVector([A₁, A₂])
@test B⃗ != FuzzyVector([A₁, A₂])

@test cut(A⃗, 0) == [Interval(0.5, 1.5), Interval(1.5, 2.5)]
@test cut(A⃗, 1) == [Interval(1), Interval(2)]

C₁ = FuzzyNumber(levels, number=-1)
C₂ = FuzzyNumber(levels, number=3)
C⃗ = FuzzyVector([C₁, C₂])

patterns = [A⃗, C⃗]
@test cut(patterns, 1, 1) == [Interval(1), Interval(-1)]
@test cut(patterns, 2, 1) == [Interval(2), Interval(3)]


text:
using CompileBot

println("tests infer benchmark")

snoop_bench(BotConfig("TestPackage2", tmin =0.0))


text:
module Voting

export  Vote,
        Votes,
        vote,

        pareto_dominates,
        condorcet,

        plurality,
        plurality_with_elimination,
        borda,
        pairwise_elimination

import Base: length, start, done, next, show, ==, hash, *

immutable Vote
    order::Array{Int64, 1}
    weight::Int64
end

==(v1::Vote, v2::Vote) = v1.order == v2.order && v1.weight == v2.weight
hash(v::Vote, h::UInt64) = hash(v.order, hash(v.weight, h))

# Iterate over order
start(vote::Vote) = 1
done(vote::Vote, index) = index > length(vote.order)
next(vote::Vote, index) = (vote.order[index], index+1)

# Construction
vote(order::Array{Int64, 1}) = Vote(order, 1)
vote(order::Int64...) = Vote(collect(order), 1)
*(v::Vote, count::Int) = Vote(v.order, v.weight * count)
*(count::Int, v::Vote) = v * count

getrank(v::Vote, a) = findfirst(v.order, a)
prefers(v::Vote, a, b) = getrank(v, a) < getrank(v, b)

function delete(v::Vote, a)
    order = map(v.order[v.order .!= a]) do c
        c > a ? c-1 : c
    end
    Vote(order, v.weight)
end

immutable Votes{T}
    ballot::Array{T, 1}
    votes::Array{Vote, 1}
end

function show(io::IO, votes::Votes)
    for v in votes
        v_ballot = votes.ballot[v.order]
        print(io, "$(v.weight)× $(v_ballot)\n")
    end
end

length(v::Vote) = length(v.order)

function Votes{T}(ballot::Array{T, 1}, votes::Array{Vote, 1})
    l = length(ballot)
    for v in votes
        if length(v) != l
            throw(ArgumentError("unexpected vote of length $(length(v)) != $l"))
        end
        if sort(v.order) != collect(1:l)
            throw(ArgumentError("order $(v.order) is not a permutation"))
        end
    end
    return Votes{T}(ballot, votes)
end

Votes{T}(ballot::Array{T, 1}, votes::Vote...) = Votes(ballot, collect(votes))

function Votes{T}(ballot::Array{T, 1}, a::Array{Int64, 2})
    m = size(a, 1)
    votes = map(1:m) do row
        ordering = collect(a[row,:])
        vote(ordering)
    end
    return Votes(ballot, votes...)
end

length{T}(votes::Votes{T}) = length(votes.votes)
start(votes::Votes) = 1
done(votes::Votes, index) = index > length(votes.votes)
next(votes::Votes, index) = (votes.votes[index], index+1)
==(votes1::Votes, votes2::Votes) = (votes1.ballot == votes2.ballot) &&
    (votes1.votes == votes2.votes)
hash(votes::Votes, h::UInt64) = hash(votes.ballot, hash(votes.votes, h))

function delete(votes::Votes, i)
    n = length(votes.ballot)
    selection = [1:i-1; i+1:n]
    return Votes(votes.ballot[selection],
    [delete(v, i) for v in votes])
end

function plurality{T}(votes::Votes{T})
    n = length(votes.ballot)
    counts = zeros(n)
    for v in votes
        counts[first(v)] += v.weight
    end
    winners = find(counts .== maximum(counts))
    return votes.ballot[winners]
end

function plurality_with_elimination{T}(votes::Votes{T})
    n = length(votes.ballot)
    if n <= 2
        return plurality(votes)
    end
    counts = zeros(n)
    for v in votes
        counts[first(v)] += v.weight
    end
    loser = indmin(counts)
    return plurality_with_elimination(delete(votes, loser))
end

# TODO(tchajed): handle ties in choice functions that use this
function prefer{T}(votes::Votes{T}, a, b)
    count_a = 0
    count_b = 0
    for v in votes
        if prefers(v, a, b)
            count_a += v.weight
        else
            count_b += v.weight
        end
    end
    return count_a > count_b
end

function pareto_dominates{T}(votes::Votes{T}, a, b)
    ai = findfirst(votes.ballot, a)
    bi = findfirst(votes.ballot, b)
    all(v -> prefers(v, ai, bi), votes)
end

function pairwise_elimination{T}(votes::Votes{T}, agenda::Array{T, 1})
    indices = [findfirst(votes.ballot, c) for c in agenda]
    while length(indices) > 1
        a = indices[1]
        b = indices[2]
        winner = prefer(votes, a, b) ? a : b
        indices = [winner; indices[3:end]]
    end
    return [votes.ballot[indices[1]]]
end

function borda{T}(votes::Votes{T})
    n = length(votes.ballot)
    counts = zeros(n)
    for v in votes, c in 1:n
        borda_count = (n - getrank(v, c)) * v.weight
        counts[c] += borda_count
    end
    winners = find(counts .== maximum(counts))
    return votes.ballot[winners]
end

function condorcet{T}(votes::Votes{T})
    n = length(votes.ballot)
    for c in 1:n
        if all(o -> prefer(votes, c, o), [1:c-1; c+1:n])
            return votes.ballot[[c]]
        end
    end
    return []
end

end


text:
@testset "construct" begin
   @test Double64(one(Double64)) === one(Double64)
   @test Double64(one(Double32)) === one(Double64)
   @test Double64(one(Double16)) === one(Double64)
   @test Double32(one(Double64)) === one(Double32)
   @test Double32(one(Double32)) === one(Double32)
   @test Double32(one(Double16)) === one(Double32)
   @test Double16(one(Double64)) === one(Double16)
   @test Double16(one(Double32)) === one(Double16)
   @test Double16(one(Double16)) === one(Double16)

   @test Double64(one(Float64)) === one(Double64)
   @test Double64(one(Float32)) === one(Double64)
   @test Double64(one(Float16)) === one(Double64)
   @test Double32(one(Float64)) === one(Double32)
   @test Double32(one(Float32)) === one(Double32)
   @test Double32(one(Float16)) === one(Double32)
   @test Double16(one(Float64)) === one(Double16)
   @test Double16(one(Float32)) === one(Double16)
   @test Double16(one(Float16)) === one(Double16)

   @test DoubleFloat(one(Double64)) === one(Double64)
   @test DoubleFloat(one(Double32)) === one(Double32)
   @test DoubleFloat(one(Double16)) === one(Double16)

   @test DoubleFloat(1.0) === one(Double64)
   @test DoubleFloat(1.0f0) === one(Double32)
   @test DoubleFloat(Float16(1.0)) === one(Double16)

   @test ComplexD64(1, 1) === ComplexD64(1.0, 1.0)
   @test ComplexD32(1, 1) === ComplexD32(1.0f0, 1.0f0)
   @test ComplexD16(1, 1) === ComplexD16(Float16(1.0), Float16(1.0))
   @test ComplexD64(1//1, -1//1) === ComplexD64(1.0, -1.0)
   @test ComplexD32(1//1, -1//1) === ComplexD32(1.0f0, -1.0f0)
   @test ComplexD16(1//1, -1//1) === ComplexD16(Float16(1.0), -Float16(1.0))
end


text:
using HTSLib
using HTSLib: htslib  # low-level API module
using Test

# Low-level API
# -------------

@testset "Low-level API" begin
    # check struct size (these sizes are derived from C's sizeof operator)
    if Sys.isunix() && Sys.ARCH == :x86_64  # LP64
        @test sizeof(htslib.kstring_t) == 24
        @test sizeof(htslib.htsFormat) == 32
        @test sizeof(htslib.htsFile) == 128
        @test sizeof(htslib.bam1_core_t) == 48
        @test sizeof(htslib.bam1_t) == 80
    end
end

# High-level API
# --------------

@testset "High-level API" begin
    @test HTSLib.HTSLIB_VERSION == v"1.10.2"
end


text:
mutable struct DrakeVisualizerSink <: OdeIntegrators.OdeResultsSink
    vis::Visualizer
    min_wall_Δt::Float64
    last_update_wall_time::Float64

    function DrakeVisualizerSink(vis::Visualizer; max_fps::Float64 = 60.)
        new(vis, 1 / max_fps, -Inf)
    end
end

function OdeIntegrators.initialize(sink::DrakeVisualizerSink, t, state)
    sink.last_update_wall_time = -Inf
    OdeIntegrators.process(sink, t, state)
end

function OdeIntegrators.process(sink::DrakeVisualizerSink, t, state)
    wall_Δt = time() - sink.last_update_wall_time
    if wall_Δt > sink.min_wall_Δt
        settransform!(sink.vis, state)
        sink.last_update_wall_time = time()
    end
    nothing
end


text:
using MathLink

e = mlinitialize()

l = mlopen(e)
mlactivate(l)

# skip initial input packet
if mlnextpacket(l) != MathLink.INPUTNAMEPKT
    error("Unexpected MathLink packet")
end
mlnewpacket(l)

# 1) log(2.0)
mlput(l,MLFunction("EvaluatePacket",1))
mlput(l,MLFunction("Log",1))
mlput(l,2.0)
mlendpacket(l)

# check for next packet
p = mlnextpacket(l)

t = mlgetnext(l) # a real
mlget(l,Float64)

# 2) using expressions
@mlput l EvaluatePacket(Log(2.0))
mlendpacket(l)

p = mlnextpacket(l)

t = mlgetnext(l) # a real
mlget(l,Float64)

@mlput l EvaluatePacket(Sin(:Pi))
mlendpacket(l)

p = mlnextpacket(l)

t = mlgetnext(l) # a real
mlget(l,Float64)

# 3) log(2)
mlput(l,MLFunction("EvaluatePacket",1))
mlput(l,MLFunction("Log",1))
mlput(l,2)
mlendpacket(l)

# check for next packet
p = mlnextpacket(l)

t = mlgetnext(l) # a function
mlgetfunction(l)

t = mlgetnext(l) # an integer
mlget(l,Int)

# 4) we can pass expressions
mlput(l,:(EvaluatePacket(Log(2))))
mlendpacket(l)

p = mlnextpacket(l)
# automatically figure out types
mlget(l)

# 5) or use strings representing Mathematica expressions
mlput(l,:(EvaluatePacket(ToExpression("Factorial[30]"))))
mlendpacket(l)

p = mlnextpacket(l)
# occasionally need to specify return types.
mlget(l,BigInt)

mlput(l,:(EvaluatePacket(Integrate(Abs(x), x, Assumptions => x > 0))))
mlendpacket(l)

p = mlnextpacket(l)
mlget(l)

bg = big(1e-30)
@mlput l EvaluatePacket(Log(CDF(GammaDistribution(1,1),bg)))
mlendpacket(l)

p = mlnextpacket(l)
mlget(l)

# done
mlclose(l)
mldeinitialize(e)


text:
module RPBounds

include("./../../constraints/geometric/constants.jl")
using JuMP
using .Constants

export rp_bounds

function rp_bounds(m)

    #Check if flbzi < flbzj < flbzi +heighti OR flbzi < flbzj+height < flbzi +height
    @variable(m, rp_ifz_1[i=1:length(boxes)-2, j=(i+1):length(boxes)-1], Bin)
    @constraint(m, rp_cifz_1[i=1:length(boxes)-2, j=(i+1):length(boxes)-1],
        m[:flbz_front_left_bot_z][i] - H * (1 - m[:rp_ifz_1][i, j]) + 0.001  <=
        m[:flbz_front_left_bot_z][j]
    )

    @variable(m, rp_ifz_2[i=1:length(boxes)-2, j=(i+1):length(boxes)-1], Bin)
    @constraint(m, rp_cifz_2[i=1:length(boxes)-2, j=(i+1):length(boxes)-1],
        m[:flbz_front_left_bot_z][j] - H * (1 - m[:rp_ifz_2][i, j])  <=
        m[:flbz_front_left_bot_z][i] + m[:hob_height_of_box][i] - 0.001
    )

    @variable(m, rp_ifz_3[i=1:length(boxes)-2, j=(i+1):length(boxes)-1], Bin)
    @constraint(m, rp_cifz_3[i=1:length(boxes)-2, j=(i+1):length(boxes)-1],
        m[:flbz_front_left_bot_z][i] - H * (1 - m[:rp_ifz_3][i, j]) + 0.001 <=
        m[:flbz_front_left_bot_z][j] + m[:hob_height_of_box][j]
    )

    @variable(m, rp_ifz_4[i=1:length(boxes)-2, j=(i+1):length(boxes)-1], Bin)
    @constraint(m, rp_cifz_4[i=1:length(boxes)-2, j=(i+1):length(boxes)-1],
        m[:flbz_front_left_bot_z][j] + m[:hob_height_of_box][j] - H * (1 - m[:rp_ifz_4][i, j])  <=
        m[:flbz_front_left_bot_z][i] + m[:hob_height_of_box][i] - 0.001
    )

    #Check if flbxi < flbxj < flbxi +xcoveri OR flbxi < flbxj+xcover < flbxi +xcoveri
    @variable(m, rp_ifx_1[i=1:length(boxes)-2, j=(i+1):length(boxes)-1], Bin)
    @constraint(m, rp_cifx_1[i=1:length(boxes)-2, j=(i+1):length(boxes)-1],
        m[:flbx_front_left_bot_x][i] - L * (1 - m[:rp_ifx_1][i, j]) + 0.001 <=
        m[:flbx_front_left_bot_x][j]
    )

    @variable(m, rp_ifx_2[i=1:length(boxes)-2, j=(i+1):length(boxes)-1], Bin)
    @constraint(m, rp_cifx_2[i=1:length(boxes)-2, j=(i+1):length(boxes)-1],
        m[:flbx_front_left_bot_x][j] - L * (1 - m[:rp_ifx_2][i, j])  <=
        m[:flbx_front_left_bot_x][i] + m[:box_x_axis_cover][i] - 0.001
    )

    @variable(m, rp_ifx_3[i=1:length(boxes)-2, j=(i+1):length(boxes)-1], Bin)
    @constraint(m, rp_cifx_3[i=1:length(boxes)-2, j=(i+1):length(boxes)-1],
        m[:flbx_front_left_bot_x][i] - L * (1 - m[:rp_ifx_3][i, j]) + 0.001 <=
        m[:flbx_front_left_bot_x][j] + m[:box_x_axis_cover][j]
    )

    @variable(m, rp_ifx_4[i=1:length(boxes)-2, j=(i+1):length(boxes)-1], Bin)
    @constraint(m, rp_cifx_4[i=1:length(boxes)-2, j=(i+1):length(boxes)-1],
        m[:flbx_front_left_bot_x][j] + m[:box_x_axis_cover][j] - L * (1 - m[:rp_ifx_4][i, j])  <=
        m[:flbx_front_left_bot_x][i] + m[:box_x_axis_cover][i] - 0.001
    )

    #Check if flbyi < flbyj < flbyi +ycoveri OR flbyi < flbyj+ycover < flbyi +ycoveri
    @variable(m, rp_ify_1[i=1:length(boxes)-2, j=(i+1):length(boxes)-1], Bin)
    @constraint(m, rp_cify_1[i=1:length(boxes)-2, j=(i+1):length(boxes)-1],
        m[:flby_front_left_bot_y][i] - W * (1 - m[:rp_ify_1][i, j]) + 0.001 <=
        m[:flby_front_left_bot_y][j]
    )

    @variable(m, rp_ify_2[i=1:length(boxes)-2, j=(i+1):length(boxes)-1], Bin)
    @constraint(m, rp_cify_2[i=1:length(boxes)-2, j=(i+1):length(boxes)-1],
        m[:flby_front_left_bot_y][j] - W * (1 - m[:rp_ify_2][i, j])  <=
        m[:flby_front_left_bot_y][i] + m[:box_y_axis_cover][i] - 0.001
    )

    @variable(m, rp_ify_3[i=1:length(boxes)-2, j=(i+1):length(boxes)-1], Bin)
    @constraint(m, rp_cify_3[i=1:length(boxes)-2, j=(i+1):length(boxes)-1],
        m[:flby_front_left_bot_y][i] - W * (1 - m[:rp_ify_3][i, j]) + 0.001 <=
        m[:flby_front_left_bot_y][j] + m[:box_y_axis_cover][j]
    )

    @variable(m, rp_ify_4[i=1:length(boxes)-2, j=(i+1):length(boxes)-1], Bin)
    @constraint(m, rp_cify_4[i=1:length(boxes)-2, j=(i+1):length(boxes)-1],
        m[:flby_front_left_bot_y][j] + m[:box_y_axis_cover][j] - W * (1 - m[:rp_ify_4][i, j])  <=
        m[:flby_front_left_bot_y][i] + m[:box_y_axis_cover][i] - 0.001
    )

    # AND Z
    @variable(m, rp_ifz_and1[i=1:length(boxes)-2, j=(i+1):length(boxes)-1], Bin)
    @constraint(m, rp_cifz_and1[i=1:length(boxes)-2, j=(i+1):length(boxes)-1],
        m[:rp_ifz_1][i, j] + m[:rp_ifz_2][i, j] >=
        2 * m[:rp_ifz_and1][i, j]
    )

    @variable(m, rp_ifz_and2[i=1:length(boxes)-2, j=(i+1):length(boxes)-1], Bin)
    @constraint(m, rp_cifz_and2[i=1:length(boxes)-2, j=(i+1):length(boxes)-1],
        m[:rp_ifz_3][i, j] + m[:rp_ifz_4][i, j] >=
        2 * m[:rp_ifz_and2][i, j]
    )

    #OR Z between flbz and flbzheight
    @variable(m, rp_ifz_or[i=1:length(boxes)-2, j=(i+1):length(boxes)-1], Bin)
    @constraint(m, rp_cifz_or[i=1:length(boxes)-2, j=(i+1):length(boxes)-1],
        m[:rp_ifz_and1][i, j] + m[:rp_ifz_and2][i, j] >=
        m[:rp_ifz_or][i, j]
    )

    # AND X
    @variable(m, rp_ifx_and1[i=1:length(boxes)-2, j=(i+1):length(boxes)-1], Bin)
    @constraint(m, rp_cifx_and1[i=1:length(boxes)-2, j=(i+1):length(boxes)-1],
        m[:rp_ifx_1][i, j] + m[:rp_ifx_2][i, j] >=
        2 * m[:rp_ifx_and1][i, j]
    )

    @variable(m, rp_ifx_and2[i=1:length(boxes)-2, j=(i+1):length(boxes)-1], Bin)
    @constraint(m, rp_cifx_and2[i=1:length(boxes)-2, j=(i+1):length(boxes)-1],
        m[:rp_ifx_3][i, j] + m[:rp_ifx_4][i, j] >=
        2 * m[:rp_ifx_and2][i, j]
    )

    #OR X between flbx and flbxcover
    @variable(m, rp_ifx_or[i=1:length(boxes)-2, j=(i+1):length(boxes)-1], Bin)
    @constraint(m, rp_cifx_or[i=1:length(boxes)-2, j=(i+1):length(boxes)-1],
        m[:rp_ifx_and1][i, j] + m[:rp_ifx_and2][i, j] >=
        m[:rp_ifx_or][i, j]
    )

    # AND Y
    @variable(m, rp_ify_and1[i=1:length(boxes)-2, j=(i+1):length(boxes)-1], Bin)
    @constraint(m, rp_cify_and1[i=1:length(boxes)-2, j=(i+1):length(boxes)-1],
        m[:rp_ify_1][i, j] + m[:rp_ify_2][i, j] >=
        2 * m[:rp_ify_and1][i, j]
    )

    @variable(m, rp_ify_and2[i=1:length(boxes)-2, j=(i+1):length(boxes)-1], Bin)
    @constraint(m, rp_cify_and2[i=1:length(boxes)-2, j=(i+1):length(boxes)-1],
        m[:rp_ify_3][i, j] + m[:rp_ify_4][i, j] >=
        2 * m[:rp_ify_and2][i, j]
    )

    #OR Y between flby and flbycover
    @variable(m, rp_ify_or[i=1:length(boxes)-2, j=(i+1):length(boxes)-1], Bin)
    @constraint(m, rp_cify_or[i=1:length(boxes)-2, j=(i+1):length(boxes)-1],
        m[:rp_ify_and1][i, j] + m[:rp_ify_and2][i, j] >=
        m[:rp_ify_or][i, j]
    )

    return m
end

end


text:
export getBoundModel,getBoundModelInv
function getBoundModel(m,a,b)
	d = (b-a)./2.0;
	mid = (b+a)./2.0;
	v = (1.0./d).*(m - mid);
	s = d.*(tanh.(v)+1) + a;
	dsdm = spdiagm(sech.(v).^2)
	return s, dsdm
end

function getBoundModelInv(s,a,b)
	d = (b-a)./2.0;
	mid = (b+a)./2.0;
    m = atanh.((s-a).*(1.0./d)-1) .* d + mid;
	return m
end


text:
"""Julia program to find the n'th number in the tribonacci series
Tribonacci series is a generalization of the Fibonacci sequence, in which the current term
is the sum of the previous three
"""

function find_tribonacci(n)
    dp = zeros(Int, n + 1)
    dp[1] = 0
    dp[2] = 0
    dp[3] = 1

    for i in 4:n
        dp[i] = dp[i-1] + dp[i-2] + dp[i-3]
    end

    return dp[n]
end

print("Enter the value of n?, where you need the n'th number in the tribonacci sequence. ")
n = readline()
n = parse(Int, n)
if (n <= 0)
    println("The given value of n is invalid.")
    exit()
end
res = find_tribonacci(n)
println("The $n'th term in the tribonacci series is $res.")

"""
Time Complexity - O(n)
Space Complexity - O(n)

SAMPLE INPUT AND OUTPUT

SAMPLE I
Enter the value of n?, where you need the n'th number in the tribonacci sequence. 12
The 12'th term in the tribonacci series is 149.

SAMPLE II
Enter the value of n?, where you need the n'th number in the tribonacci sequence. 1254
The 1254'th term in the tribonacci series is 4020147461713125140.
"""

max_issues_repo_name: adarshnjena/NeoAlgo

max_forks_repo_name: adarshnjena/NeoAlgo


text:
# Package StatsBase, Distributions, JuMP, Gurobi are needed!
function BernsteinEstimate_MIQO(Y,m,a,b,k,e,T)
     n = size(Y,1)
     M = Model(with_optimizer(Gurobi.Optimizer, TimeLimit = T, MIPGap = e))
     #M = Model(solver = GurobiSolver(TimeLimit = T, MIPGap = e))

     @variable(M, w[1:m]>=0)
     @variable(M, z[1:m-1], Bin)
     @variable(M, σ_plus[1:m-2], Bin)
     @variable(M, σ_minus[1:m-2], Bin)
     @variable(M, α[1:m-2,1:2], Bin)

    # Uncomment this line for doing a warmstart
    #setvalue(w, BernsteinEstimate_MD(Y,m,a,b,0)')

    @constraint(M, sum(w)==1);
    # A big constant
    K = 1
    # k-modality constraint
    if k>=1
        for j=1:m-1
            @constraint(M, w[j]<=w[j+1]+K*z[j]);
            @constraint(M, w[j]>=w[j+1]-K*(1-z[j]));
        end
        for j=1:m-2
            @constraint(M, z[j+1]-z[j]==σ_plus[j]-σ_minus[j]);
            @constraint(M, σ_plus[j]<=K*α[j,1]);
            @constraint(M, σ_minus[j]<=K*α[j,2]);
            @constraint(M, α[j,1]+α[j,2]==1);
        end
        @constraint(M, sum(σ_plus)<=k);
        @constraint(M, sum(σ_minus)<=k);
    end

    ϵ = 3/(8*n)
    Ecdf = ecdf(vec(Y))

    B = zeros(n,m)
    f = zeros(n,1)
    for i = 1:n
        f[i] = Ecdf(Y[i])
    end

    diag_L = (1 ./((Ecdf(Y).+ϵ).*(1+ϵ.-Ecdf(Y)))).^0.5
    L = diagm(0 => diag_L)

    for i=1:n
        for j=1:m
            B[i,j] = betacdf(j, m-j+1, (Y[i]-a)/(b-a))
        end
    end

    #svd approximation - for numerical stability
    Q1 =(L*B)';
    Q = Q1*Q1';

    SVD_Q1 = svd(Q1)
    ids = SVD_Q1.S.>10e-3;
    vals = SVD_Q1.S[ids];
    uu = SVD_Q1.U[:,ids];

    Qhat = uu*diagm(0 => vals.^2)*uu'
    Qhat = (Qhat + Qhat')/2 + 0.001*Matrix{Float64}(I,m,m);

    V = (L*f)'*(L*B)

    c1 = sum(diag(V))
    c2 = sum(diag(Qhat))

    @objective(M, Min, -2*sum(V[i]*w[i] for i=1:m) + sum(Qhat[i,j]*w[i]*w[j] for i=1:m for j=1:m) )

    optimize!(M)

    return JuMP.value.(w)

end

max_stars_repo_name: visuddhi/UnivariateDensityEstimate

max_issues_repo_name: visuddhi/UnivariateDensityEstimate

max_forks_repo_name: visuddhi/UnivariateDensityEstimate


text:
module DisplayStructure

    using Terming
    const T = Terming

    include("util.jl")
    include("display_row.jl")
    include("display_array.jl")
    include("feature/feature.jl")

end


text:
using Thrift
import Thrift.process, Thrift.meta

include("gen-jl/floatops/floatops_constants.jl");
include("gen-jl/floatops/floatops_types.jl");
include("gen-jl/floatops/FloatCalc.jl");

include("gen-jl/arithmetic/arithmetic_constants.jl");
include("gen-jl/arithmetic/arithmetic_types.jl");
include("gen-jl/arithmetic/Calc.jl");

function calculate(oper::AbstractString, p1::Int32, p2::Int32)
    ret = (eval(symbol(oper)))(p1, p2)
    if ret > (2^31 - 1)
        ex = InvalidOperation()
        set_field!(ex, :oper, "$oper($p1, $p2) overflows")
        throw(ex)
    end
    ret
end

function float_calculate(oper::AbstractString, p1::Float64, p2::Float64)
    ret = (eval(symbol(oper)))(p1, p2)
    if ret > (2^63 - 1)
        ex = InvalidFloatOperation()
        set_field!(ex, :oper, "$oper($p1, $p2) overflows")
        throw(ex)
    end
    ret
end

function calcsrvr()
    cp = CalcProcessor()
    srvr_transport = TServerSocket(19999)
    srvr = TSimpleServer(srvr_transport, cp, x->x, x->TBinaryProtocol(x), x->x, x->TBinaryProtocol(x))
    #srvr = TSimpleServer(srvr_transport, cp, x->x, x->TCompactProtocol(x), x->x, x->TCompactProtocol(x))
    println("starting julia server...")
    serve(srvr)
    println("server stopped")
end

calcsrvr()


text:
import Base.show
export show

# A set variable, for example, Variable([1, 3]), will be displayed as:
# SetVariable of
# baseset: [1, 3]
# sign: NoSign()
# modularity: ConstModularity()
function show(io::IO, x::SetVariable)
  print(io, """SetVariable of
    baseset: $(x.baseset)""")
  if x.elements != nothing
    print(io, "\nelements: $(x.elements)")
  end
end

# A combinatorial set, for example, GenCombiSet([1, 3]), will be displayed as:
# CombiSet of
# baseset: [1, 3]
# sign: NoSign()
# modularity: ConstModularity()
function show(io::IO, x::CombiSet)
  print(io, """CombiSet of
    baseset: $(x.baseset)""")
  if x.elements != nothing
    print(io, "\nelements: $(x.elements)")
  end
end

# An combinatorial function, for example, card(x)^2, will be displayed as:
# SubmodFunc with
# head: card
# size: (1, 1)
# sign: Positive()
# modularity: SuperModularity()
function show(io::IO, f::SubmodFunc)
  print(io, """SubmodFunc with
    head: $(f.head)
    size: ($(f.size[1]), $(f.size[2]))
    sign: $(sign(f))
    modularity: $(modularity(f))
    """)
end

# An polyhedron asssociated with f, for example, subpoly(f), will be dispayed as:
# AssocPoly with
# head: card
# baseset: [1, 2]
# function: f
function show(io::IO, p::AssocPoly)
  print(io, """AssocPoly with
    head: $(p.head)
    baseset: $(p.V)
    associated to $(p.F)""")
end

# A set constraint, for example, in(x, p), will be displayed as:
# Constraint:
# set constraint
# lhs: ...
# rhs: ...
function show(io::IO, c::SetConstraint)
  print(io, """Constraint:
    $(c.head) constraint
    set: $(c.rhs)""")
end


text:
@testset "Events/Element Declarations" begin
    evaluate(s) = collect(E.events(L.State(IOBuffer(s))))

    E = Events
    L = Events.Lexical

    ED = Events.ElementDeclaration

    CMAny   = Events.AnyModel
    CMEmpty = Events.EmptyModel
    CMMixed = Events.MixedModel

    CMElement = Events.ElementModel

    Choice   = Events.ChoiceGroup
    Sequence = Events.SequenceGroup

    OneOrMore  = Events.OneOrMore
    Optional   = Events.Optional
    ZeroOrMore = Events.ZeroOrMore

    DC = E.DataContent
    ME = E.MarkupError

    @testset "Events/Element Declarations, ANY (Positive)" begin
        # Verify that the element name is handled properly ... just use ANY for the content model.
        #
        @test evaluate("<!ELEMENT a ANY>")   == [ ED(false, "a", CMAny(), L.Location("a buffer", -1)) ]
        @test evaluate("<!ELEMENT abc ANY>") == [ ED(false, "abc", CMAny(), L.Location("a buffer", -1)) ]
        @test evaluate("<!ELEMENT é ANY>")   == [ ED(false, "é", CMAny(), L.Location("a buffer", -1)) ]
        @test evaluate("<!ELEMENT aé ANY>")  == [ ED(false, "aé", CMAny(), L.Location("a buffer", -1)) ]
        @test evaluate("<!ELEMENT éb ANY>")  == [ ED(false, "éb", CMAny(), L.Location("a buffer", -1)) ]
        @test evaluate("<!ELEMENT aéb ANY>") == [ ED(false, "aéb", CMAny(), L.Location("a buffer", -1)) ]

        # White space is required following the element name. Just try various combinations, and check that it is
        # discarded.
        #
        @test evaluate("<!ELEMENT a\tANY>")    == [ ED(false, "a", CMAny(), L.Location("a buffer", -1)) ]
        @test evaluate("<!ELEMENT a	ANY>") == [ ED(false, "a", CMAny(), L.Location("a buffer", -1)) ]
        @test evaluate("<!ELEMENT a\n\nANY>")  == [ ED(false, "a", CMAny(), L.Location("a buffer", -1)) ]

        # Verify that the ANY content model is handled properly. This is mostly a matter of verifying that trailing
        # white space is discarded.
        #
        @test evaluate("<!ELEMENT a ANY >")        == [ ED(false, "a", CMAny(), L.Location("a buffer", -1)) ]
        @test evaluate("<!ELEMENT a ANY        >") == [ ED(false, "a", CMAny(), L.Location("a buffer", -1)) ]
        @test evaluate("<!ELEMENT a ANY\t>")       == [ ED(false, "a", CMAny(), L.Location("a buffer", -1)) ]
        @test evaluate("<!ELEMENT a ANY\n>")       == [ ED(false, "a", CMAny(), L.Location("a buffer", -1)) ]
        @test evaluate("<!ELEMENT a ANY\n\t>")     == [ ED(false, "a", CMAny(), L.Location("a buffer", -1)) ]
        @test evaluate("<!ELEMENT a ANY\u09>")     == [ ED(false, "a", CMAny(), L.Location("a buffer", -1)) ]
    end

    @testset "Events/Element Declarations, EMPTY (Positive)" begin
        # Verify that the EMPTY content model is handled properly. This is mostly a matter of verifying that trailing
        # white space is discarded.
        #
        @test evaluate("<!ELEMENT a EMPTY >")        == [ ED(false, "a", CMEmpty(), L.Location("a buffer", -1)) ]
        @test evaluate("<!ELEMENT a EMPTY        >") == [ ED(false, "a", CMEmpty(), L.Location("a buffer", -1)) ]
        @test evaluate("<!ELEMENT a EMPTY\t>")       == [ ED(false, "a", CMEmpty(), L.Location("a buffer", -1)) ]
        @test evaluate("<!ELEMENT a EMPTY\n>")       == [ ED(false, "a", CMEmpty(), L.Location("a buffer", -1)) ]
        @test evaluate("<!ELEMENT a EMPTY\n\t>")     == [ ED(false, "a", CMEmpty(), L.Location("a buffer", -1)) ]
        @test evaluate("<!ELEMENT a EMPTY\u09>")     == [ ED(false, "a", CMEmpty(), L.Location("a buffer", -1)) ]
    end

    @testset "Events/Element Declarations, Mixed Content (Positive)" begin
        # Verify that a mixed content model is handled properly. Assuming minimal white space for now.
        #
        @test evaluate("<!ELEMENT a (#PCDATA)>")  == [ ED(false, "a", CMMixed([ ]), L.Location("a buffer", -1)) ]
        @test evaluate("<!ELEMENT a (#PCDATA)*>") == [ ED(false, "a", CMMixed([ ]), L.Location("a buffer", -1)) ]

        @test (evaluate("<!ELEMENT a (#PCDATA|b)*>")
               == [ ED(false, "a", CMMixed([ CMElement("b") ]), L.Location("a buffer", -1)) ])
        @test (evaluate("<!ELEMENT a (#PCDATA|b|c)*>")
               == [ ED(false, "a", CMMixed([ CMElement("b"), CMElement("c") ]), L.Location("a buffer", -1)) ])
        @test (evaluate("<!ELEMENT a (#PCDATA|b|c|d)*>")
               == [ ED(false, "a", CMMixed([ CMElement("b"), CMElement("c"), CMElement("d") ]), L.Location("a buffer", -1)) ])

        # Still working with a mixed content model, verify that the child elements are handled properly.
        #
        @test (evaluate("<!ELEMENT a (#PCDATA|bcd)*>")
               == [ ED(false, "a", CMMixed([ CMElement("bcd") ]), L.Location("a buffer", -1)) ])
        @test (evaluate("<!ELEMENT a (#PCDATA|é)*>")
               == [ ED(false, "a", CMMixed([ CMElement("é") ]), L.Location("a buffer", -1)) ])
        @test (evaluate("<!ELEMENT a (#PCDATA|bé)*>")
               == [ ED(false, "a", CMMixed([ CMElement("bé") ]), L.Location("a buffer", -1)) ])
        @test (evaluate("<!ELEMENT a (#PCDATA|éc)*>")
               == [ ED(false, "a", CMMixed([ CMElement("éc") ]), L.Location("a buffer", -1)) ])
        @test (evaluate("<!ELEMENT a (#PCDATA|béc)*>")
               == [ ED(false, "a", CMMixed([ CMElement("béc") ]), L.Location("a buffer", -1)) ])

        @test (evaluate("<!ELEMENT a (#PCDATA|b|cde)*>")
               == [ ED(false, "a", CMMixed([ CMElement("b"), CMElement("cde") ]), L.Location("a buffer", -1)) ])
        @test (evaluate("<!ELEMENT a (#PCDATA|b|é)*>")
               == [ ED(false, "a", CMMixed([ CMElement("b"), CMElement("é") ]), L.Location("a buffer", -1)) ])
        @test (evaluate("<!ELEMENT a (#PCDATA|b|cé)*>")
               == [ ED(false, "a", CMMixed([ CMElement("b"), CMElement("cé") ]), L.Location("a buffer", -1)) ])
        @test (evaluate("<!ELEMENT a (#PCDATA|b|éc)*>")
               == [ ED(false, "a", CMMixed([ CMElement("b"), CMElement("éc") ]), L.Location("a buffer", -1)) ])
        @test (evaluate("<!ELEMENT a (#PCDATA|b|céd)*>")
               == [ ED(false, "a", CMMixed([ CMElement("b"), CMElement("céd") ]), L.Location("a buffer", -1)) ])

        # Finally, verify that the various combinations of spurious white space in a mixed content model are handled
        # properly.
        #
        @test (evaluate("<!ELEMENT a  (#PCDATA| b)*>")
               == [ ED(false, "a", CMMixed([ CMElement("b") ]), L.Location("a buffer", -1)) ])
        @test (evaluate("<!ELEMENT a\n(#PCDATA| b)*>")
               == [ ED(false, "a", CMMixed([ CMElement("b") ]), L.Location("a buffer", -1)) ])
        @test (evaluate("<!ELEMENT a\t(#PCDATA| b)*>")
               == [ ED(false, "a", CMMixed([ CMElement("b") ]), L.Location("a buffer", -1)) ])

        @test (evaluate("<!ELEMENT a (#PCDATA| b)*>")
               == [ ED(false, "a", CMMixed([ CMElement("b") ]), L.Location("a buffer", -1)) ])
        @test (evaluate("<!ELEMENT a (#PCDATA |b)*>")
               == [ ED(false, "a", CMMixed([ CMElement("b") ]), L.Location("a buffer", -1)) ])
        @test (evaluate("<!ELEMENT a (#PCDATA | b)*>")
               == [ ED(false, "a", CMMixed([ CMElement("b") ]), L.Location("a buffer", -1)) ])
        @test (evaluate("<!ELEMENT a (#PCDATA| b )*>")
               == [ ED(false, "a", CMMixed([ CMElement("b") ]), L.Location("a buffer", -1)) ])
        @test (evaluate("<!ELEMENT a (#PCDATA\t|\nb\t)*>")
               == [ ED(false, "a", CMMixed([ CMElement("b") ]), L.Location("a buffer", -1)) ])

        @test (evaluate("<!ELEMENT a (#PCDATA|b| c)*>")
               == [ ED(false, "a", CMMixed([ CMElement("b"), CMElement("c") ]), L.Location("a buffer", -1)) ])
        @test (evaluate("<!ELEMENT a (#PCDATA|b|c )*>")
               == [ ED(false, "a", CMMixed([ CMElement("b"), CMElement("c") ]), L.Location("a buffer", -1)) ])
        @test (evaluate("<!ELEMENT a (#PCDATA|b| c )*>")
               == [ ED(false, "a", CMMixed([ CMElement("b"), CMElement("c") ]), L.Location("a buffer", -1)) ])
        @test (evaluate("<!ELEMENT a (#PCDATA|b\t|\tc\n)*>")
               == [ ED(false, "a", CMMixed([ CMElement("b"), CMElement("c") ]), L.Location("a buffer", -1)) ])

        @test (evaluate("<!ELEMENT a (#PCDATA|b\t|\tc\n)*\n>")
               == [ ED(false, "a", CMMixed([ CMElement("b"), CMElement("c") ]), L.Location("a buffer", -1)) ])
    end

    @testset "Events/Element Declarations, Mixed Content (Negative ... missing leading white space)" begin
        @test (evaluate("<!ELEMENT a(#PCDATA)>")
               == [ ME("ERROR: White space is required following an element name.", L.Location("a buffer", -1)),
                    ED(true, "a", CMMixed([ ]), L.Location("a buffer", -1)) ])
    end

    @testset "Events/Element Declarations, Mixed Content (Negative ... missing trailing occurrence indicator)" begin
        @test (evaluate("<!ELEMENT a (#PCDATA | b)>")
               == [ ME("ERROR: Expecting '*' to end a mixed content model.", L.Location("a buffer", -1)),
                    ED(true, "a", CMMixed([ CMElement("b") ]), L.Location("a buffer", -1)) ])
    end

    @testset "Events/Element Declarations, Mixed Content (Negative ... missing GRPC)" begin
        @test (evaluate("<!ELEMENT a (#PCDATA>")
               == [ ME("ERROR: Expecting ')*' to end a mixed content model.", L.Location("a buffer", -1)),
                    ED(true, "a", CMMixed([ ]), L.Location("a buffer", -1)) ])
    end

    @testset "Events/Element Declarations, Mixed Content (Negative ... missing element name)" begin
        @test (evaluate("<!ELEMENT a (#PCDATA||b)*>")
               == [ ME("ERROR: Expecting an element name.", L.Location("a buffer", -1)),
                    ED(true, "a", CMMixed([ CMElement("b") ]), L.Location("a buffer", -1)) ])

        @test (evaluate("<!ELEMENT a (#PCDATA|)*>")
               == [ ME("ERROR: Expecting an element name.", L.Location("a buffer", -1)),
                    ED(true, "a", CMMixed([ ]), L.Location("a buffer", -1)) ])
    end

    @testset "Events/Element Declarations, Mixed Content (Negative ... missing separator)" begin
        @test (evaluate("<!ELEMENT a (#PCDATA b)*>")
               == [ ME("ERROR: Items in a mixed content model must be separated by '|'.", L.Location("a buffer", -1)),
                    ED(true, "a", CMMixed([ CMElement("b") ]), L.Location("a buffer", -1)) ])
    end

    @testset "Events/Element Declarations, Mixed Content (Negative ... out of position #PCDATA)" begin
        @test (evaluate("<!ELEMENT a (#PCDATA|#PCDATA)>")
               == [ ME("ERROR: '#PCDATA' can only appear at the start of a mixed content model.", L.Location("a buffer", -1)),
                    ED(true, "a", CMMixed([ ]), L.Location("a buffer", -1)) ])

        @test (evaluate("<!ELEMENT a (#PCDATA b #PCDATA)*>")
               == [ ME("ERROR: Items in a mixed content model must be separated by '|'.", L.Location("a buffer", -1)),
                    ME("ERROR: '#PCDATA' can only appear at the start of a mixed content model.", L.Location("a buffer", -1)),
                    ED(true, "a", CMMixed([ CMElement("b") ]), L.Location("a buffer", -1)) ])
    end

    @testset "Events/Element Declarations, Element Content (Positive)" begin
        # Verify that a single-child element content model is handled properly. Assuming minimal white space for now.
        #
        @test evaluate("<!ELEMENT a (b)>")  == [ ED(false, "a", CMElement("b"), L.Location("a buffer", -1)) ]
        @test evaluate("<!ELEMENT a (b)+>") == [ ED(false, "a", OneOrMore(CMElement("b")), L.Location("a buffer", -1)) ]
        @test evaluate("<!ELEMENT a (b)?>") == [ ED(false, "a", Optional(CMElement("b")), L.Location("a buffer", -1)) ]
        @test evaluate("<!ELEMENT a (b)*>") == [ ED(false, "a", ZeroOrMore(CMElement("b")), L.Location("a buffer", -1)) ]

        # Fiddle with the white space.
        #
        @test evaluate("<!ELEMENT a  (b)>") == [ ED(false, "a", CMElement("b"), L.Location("a buffer", -1)) ]
        @test evaluate("<!ELEMENT a\n(b)>") == [ ED(false, "a", CMElement("b"), L.Location("a buffer", -1)) ]
        @test evaluate("<!ELEMENT a\t(b)>") == [ ED(false, "a", CMElement("b"), L.Location("a buffer", -1)) ]

        @test evaluate("<!ELEMENT a ( b)>")      == [ ED(false, "a", CMElement("b"), L.Location("a buffer", -1)) ]
        @test evaluate("<!ELEMENT a (b )>")      == [ ED(false, "a", CMElement("b"), L.Location("a buffer", -1)) ]
        @test evaluate("<!ELEMENT a (b) >")      == [ ED(false, "a", CMElement("b"), L.Location("a buffer", -1)) ]
        @test evaluate("<!ELEMENT a (\nb\t)\n>") == [ ED(false, "a", CMElement("b"), L.Location("a buffer", -1)) ]

        @test evaluate("<!ELEMENT a (b)+>")       == [ ED(false, "a", OneOrMore(CMElement("b")), L.Location("a buffer", -1)) ]
        @test evaluate("<!ELEMENT a ( b)+>")      == [ ED(false, "a", OneOrMore(CMElement("b")), L.Location("a buffer", -1)) ]
        @test evaluate("<!ELEMENT a (b )+>")      == [ ED(false, "a", OneOrMore(CMElement("b")), L.Location("a buffer", -1)) ]
        @test evaluate("<!ELEMENT a (b)+ >")      == [ ED(false, "a", OneOrMore(CMElement("b")), L.Location("a buffer", -1)) ]
        @test evaluate("<!ELEMENT a (\nb\t)\n+>") == [ ED(false, "a", OneOrMore(CMElement("b")), L.Location("a buffer", -1)) ]
        @test evaluate("<!ELEMENT a (b)\n+\t>")   == [ ED(false, "a", OneOrMore(CMElement("b")), L.Location("a buffer", -1)) ]

        @test evaluate("<!ELEMENT a (b)?>")       == [ ED(false, "a", Optional(CMElement("b")), L.Location("a buffer", -1)) ]
        @test evaluate("<!ELEMENT a ( b)?>")      == [ ED(false, "a", Optional(CMElement("b")), L.Location("a buffer", -1)) ]
        @test evaluate("<!ELEMENT a (b )?>")      == [ ED(false, "a", Optional(CMElement("b")), L.Location("a buffer", -1)) ]
        @test evaluate("<!ELEMENT a (b)? >")      == [ ED(false, "a", Optional(CMElement("b")), L.Location("a buffer", -1)) ]
        @test evaluate("<!ELEMENT a (\nb\t)\n?>") == [ ED(false, "a", Optional(CMElement("b")), L.Location("a buffer", -1)) ]
        @test evaluate("<!ELEMENT a (b)\n?\t>")   == [ ED(false, "a", Optional(CMElement("b")), L.Location("a buffer", -1)) ]

        @test evaluate("<!ELEMENT a (b)*>")       == [ ED(false, "a", ZeroOrMore(CMElement("b")), L.Location("a buffer", -1)) ]
        @test evaluate("<!ELEMENT a ( b)*>")      == [ ED(false, "a", ZeroOrMore(CMElement("b")), L.Location("a buffer", -1)) ]
        @test evaluate("<!ELEMENT a (b )*>")      == [ ED(false, "a", ZeroOrMore(CMElement("b")), L.Location("a buffer", -1)) ]
        @test evaluate("<!ELEMENT a (b)* >")      == [ ED(false, "a", ZeroOrMore(CMElement("b")), L.Location("a buffer", -1)) ]
        @test evaluate("<!ELEMENT a (\nb\t)\n*>") == [ ED(false, "a", ZeroOrMore(CMElement("b")), L.Location("a buffer", -1)) ]
        @test evaluate("<!ELEMENT a (b)*\t>")     == [ ED(false, "a", ZeroOrMore(CMElement("b")), L.Location("a buffer", -1)) ]

        # Verify that a choice-group content model is handled properly. Assuming minimal white space and no occurrence
        # indicator for now.
        #
        @test (evaluate("<!ELEMENT a (b|c)>")
               == [ ED(false, "a", Choice([ CMElement("b"), CMElement("c") ]), L.Location("a buffer", -1)) ])
        @test (evaluate("<!ELEMENT a (b|c|d)>")
               == [ ED(false, "a", Choice([ CMElement("b"), CMElement("c"), CMElement("d") ]), L.Location("a buffer", -1)) ])

        # Fiddle with the white space.
        #
        @test (evaluate("<!ELEMENT a  (b|c)>")
               == [ ED(false, "a", Choice([ CMElement("b"), CMElement("c") ]), L.Location("a buffer", -1)) ])
        @test (evaluate("<!ELEMENT a\n(b|c)>")
               == [ ED(false, "a", Choice([ CMElement("b"), CMElement("c") ]), L.Location("a buffer", -1)) ])
        @test (evaluate("<!ELEMENT a \t(b|c)>")
               == [ ED(false, "a", Choice([ CMElement("b"), CMElement("c") ]), L.Location("a buffer", -1)) ])

        @test (evaluate("<!ELEMENT a ( b|c)>")
               == [ ED(false, "a", Choice([ CMElement("b"), CMElement("c") ]), L.Location("a buffer", -1)) ])
        @test (evaluate("<!ELEMENT a (b |c)>")
               == [ ED(false, "a", Choice([ CMElement("b"), CMElement("c") ]), L.Location("a buffer", -1)) ])
        @test (evaluate("<!ELEMENT a ( b |c)>")
               == [ ED(false, "a", Choice([ CMElement("b"), CMElement("c") ]), L.Location("a buffer", -1)) ])

        @test (evaluate("<!ELEMENT a (b| c)>")
               == [ ED(false, "a", Choice([ CMElement("b"), CMElement("c") ]), L.Location("a buffer", -1)) ])
        @test (evaluate("<!ELEMENT a (b|c )>")
               == [ ED(false, "a", Choice([ CMElement("b"), CMElement("c") ]), L.Location("a buffer", -1)) ])
        @test (evaluate("<!ELEMENT a (b| c )>")
               == [ ED(false, "a", Choice([ CMElement("b"), CMElement("c") ]), L.Location("a buffer", -1)) ])

        @test (evaluate("<!ELEMENT a ( b | c )>")
               == [ ED(false, "a", Choice([ CMElement("b"), CMElement("c") ]), L.Location("a buffer", -1)) ])
        @test (evaluate("<!ELEMENT a ( b | c ) >")
               == [ ED(false, "a", Choice([ CMElement("b"), CMElement("c") ]), L.Location("a buffer", -1)) ])

        # Throw in an occurrence indicator.
        #
        @test (evaluate("<!ELEMENT a (b|c)+>")
               == [ ED(false, "a", OneOrMore(Choice([ CMElement("b"), CMElement("c") ])), L.Location("a buffer", -1)) ])
        @test (evaluate("<!ELEMENT a (b|c)?>")
               == [ ED(false, "a", Optional(Choice([ CMElement("b"), CMElement("c") ])), L.Location("a buffer", -1)) ])
        @test (evaluate("<!ELEMENT a (b|c)*>")
               == [ ED(false, "a", ZeroOrMore(Choice([ CMElement("b"), CMElement("c") ])), L.Location("a buffer", -1)) ])

        # Verify that a sequence-group content model is handled properly. Assuming minimal white space and no occurrence
        # indicator for now.
        #
        @test (evaluate("<!ELEMENT a (b,c)>")
               == [ ED(false, "a", Sequence([ CMElement("b"), CMElement("c") ]), L.Location("a buffer", -1)) ])
        @test (evaluate("<!ELEMENT a (b,c,d)>")
               == [ ED(false, "a", Sequence([ CMElement("b"), CMElement("c"), CMElement("d") ]), L.Location("a buffer", -1)) ])

        # Fiddle with the white space.
        #
        @test (evaluate("<!ELEMENT a  (b,c)>")
               == [ ED(false, "a", Sequence([ CMElement("b"), CMElement("c") ]), L.Location("a buffer", -1)) ])
        @test (evaluate("<!ELEMENT a\n(b,c)>")
               == [ ED(false, "a", Sequence([ CMElement("b"), CMElement("c") ]), L.Location("a buffer", -1)) ])
        @test (evaluate("<!ELEMENT a \t(b,c)>")
               == [ ED(false, "a", Sequence([ CMElement("b"), CMElement("c") ]), L.Location("a buffer", -1)) ])

        @test (evaluate("<!ELEMENT a ( b,c)>")
               == [ ED(false, "a", Sequence([ CMElement("b"), CMElement("c") ]), L.Location("a buffer", -1)) ])
        @test (evaluate("<!ELEMENT a (b ,c)>")
               == [ ED(false, "a", Sequence([ CMElement("b"), CMElement("c") ]), L.Location("a buffer", -1)) ])
        @test (evaluate("<!ELEMENT a ( b ,c)>")
               == [ ED(false, "a", Sequence([ CMElement("b"), CMElement("c") ]), L.Location("a buffer", -1)) ])

        @test (evaluate("<!ELEMENT a (b, c)>")
               == [ ED(false, "a", Sequence([ CMElement("b"), CMElement("c") ]), L.Location("a buffer", -1)) ])
        @test (evaluate("<!ELEMENT a (b,c )>")
               == [ ED(false, "a", Sequence([ CMElement("b"), CMElement("c") ]), L.Location("a buffer", -1)) ])
        @test (evaluate("<!ELEMENT a (b, c )>")
               == [ ED(false, "a", Sequence([ CMElement("b"), CMElement("c") ]), L.Location("a buffer", -1)) ])

        @test (evaluate("<!ELEMENT a ( b , c )>")
               == [ ED(false, "a", Sequence([ CMElement("b"), CMElement("c") ]), L.Location("a buffer", -1)) ])
        @test (evaluate("<!ELEMENT a ( b , c ) >")
               == [ ED(false, "a", Sequence([ CMElement("b"), CMElement("c") ]), L.Location("a buffer", -1)) ])

        # Throw in an occurrence indicator.
        #
        @test (evaluate("<!ELEMENT a (b,c)+>")
               == [ ED(false, "a", OneOrMore(Sequence([ CMElement("b"), CMElement("c") ])), L.Location("a buffer", -1)) ])
        @test (evaluate("<!ELEMENT a (b,c)?>")
               == [ ED(false, "a", Optional(Sequence([ CMElement("b"), CMElement("c") ])), L.Location("a buffer", -1)) ])
        @test (evaluate("<!ELEMENT a (b,c)*>")
               == [ ED(false, "a", ZeroOrMore(Sequence([ CMElement("b"), CMElement("c") ])), L.Location("a buffer", -1)) ])

        # Verify that nested groups are handled properly. Assuming minimal white space and no occurrence indicator for
        # now.
        #
        @test (evaluate("<!ELEMENT a (b,(c))>")
               == [ ED(false, "a", Sequence([ CMElement("b"), CMElement("c") ]), L.Location("a buffer", -1)) ])
        @test (evaluate("<!ELEMENT a (b,(c|d))>")
               == [ ED(false, "a", Sequence([ CMElement("b"), Choice([ CMElement("c"), CMElement("d") ]) ]),
                       L.Location("a buffer", -1)) ])
        @test (evaluate("<!ELEMENT a (b,(c,d))>")
               == [ ED(false, "a", Sequence([ CMElement("b"), Sequence([ CMElement("c"), CMElement("d") ]) ]),
                       L.Location("a buffer", -1)) ])

        @test (evaluate("<!ELEMENT a ((c),b)>")
               == [ ED(false, "a", Sequence([ CMElement("c"), CMElement("b") ]), L.Location("a buffer", -1)) ])
        @test (evaluate("<!ELEMENT a ((c|d),b)>")
               == [ ED(false, "a", Sequence([ Choice([ CMElement("c"), CMElement("d") ]), CMElement("b") ]),
                       L.Location("a buffer", -1)) ])
        @test (evaluate("<!ELEMENT a ((c,d),b)>")
               == [ ED(false, "a", Sequence([ Sequence([ CMElement("c"), CMElement("d") ]), CMElement("b") ]),
                       L.Location("a buffer", -1)) ])

        @test (evaluate("<!ELEMENT a (b,(c),e)>")
               == [ ED(false, "a", Sequence([ CMElement("b"), CMElement("c"), CMElement("e") ]), L.Location("a buffer", -1)) ])
        @test (evaluate("<!ELEMENT a (b,(c|d),e)>")
               == [ ED(false, "a", Sequence([ CMElement("b"), Choice([ CMElement("c"), CMElement("d") ]), CMElement("e") ]),
                       L.Location("a buffer", -1)) ])
        @test (evaluate("<!ELEMENT a (b,(c,d),e)>")
               == [ ED(false, "a", Sequence([ CMElement("b"), Sequence([ CMElement("c"), CMElement("d") ]), CMElement("e") ]),
                       L.Location("a buffer", -1)) ])

        @test (evaluate("<!ELEMENT a ((c),b,(d))>")
               == [ ED(false, "a", Sequence([ CMElement("c"), CMElement("b"), CMElement("d") ]), L.Location("a buffer", -1)) ])
        @test (evaluate("<!ELEMENT a ((c|d),b,(e|f))>")
               == [ ED(false, "a", Sequence([ Choice([ CMElement("c"), CMElement("d") ]), CMElement("b"),
                                              Choice([ CMElement("e"), CMElement("f") ]) ]),
                       L.Location("a buffer", -1)) ])
        @test (evaluate("<!ELEMENT a ((c,d),b,(e,f))>")
               == [ ED(false, "a", Sequence([ Sequence([ CMElement("c"), CMElement("d") ]), CMElement("b"),
                                              Sequence([ CMElement("e"), CMElement("f") ])]),
                       L.Location("a buffer", -1)) ])

        # Pick one group and add occurrence indicators.
        #
        @test (evaluate("<!ELEMENT a ((c)+,b,(d))>")
               == [ ED(false, "a", Sequence([ OneOrMore(CMElement("c")), CMElement("b"), CMElement("d") ]),
                       L.Location("a buffer", -1)) ])
        @test (evaluate("<!ELEMENT a ((c|d)+,b,(e|f))>")
               == [ ED(false, "a", Sequence([ OneOrMore(Choice([ CMElement("c"), CMElement("d") ])), CMElement("b"),
                                              Choice([ CMElement("e"), CMElement("f") ]) ]),
                       L.Location("a buffer", -1)) ])
        @test (evaluate("<!ELEMENT a ((c,d)+,b,(e,f))>")
               == [ ED(false, "a", Sequence([ OneOrMore(Sequence([ CMElement("c"), CMElement("d") ])), CMElement("b"),
                                              Sequence([ CMElement("e"), CMElement("f") ])]),
                       L.Location("a buffer", -1)) ])

        @test (evaluate("<!ELEMENT a ((c)?,b,(d))>")
               == [ ED(false, "a", Sequence([ Optional(CMElement("c")), CMElement("b"), CMElement("d") ]),
                       L.Location("a buffer", -1)) ])
        @test (evaluate("<!ELEMENT a ((c|d)?,b,(e|f))>")
               == [ ED(false, "a", Sequence([ Optional(Choice([ CMElement("c"), CMElement("d") ])), CMElement("b"),
                                              Choice([ CMElement("e"), CMElement("f") ]) ]),
                       L.Location("a buffer", -1)) ])
        @test (evaluate("<!ELEMENT a ((c,d)?,b,(e,f))>")
               == [ ED(false, "a", Sequence([ Optional(Sequence([ CMElement("c"), CMElement("d") ])), CMElement("b"),
                                              Sequence([ CMElement("e"), CMElement("f") ])]),
                       L.Location("a buffer", -1)) ])

        @test (evaluate("<!ELEMENT a ((c)*,b,(d))>")
               == [ ED(false, "a", Sequence([ ZeroOrMore(CMElement("c")), CMElement("b"), CMElement("d") ]),
                       L.Location("a buffer", -1)) ])
        @test (evaluate("<!ELEMENT a ((c|d)*,b,(e|f))>")
               == [ ED(false, "a", Sequence([ ZeroOrMore(Choice([ CMElement("c"), CMElement("d") ])), CMElement("b"),
                                              Choice([ CMElement("e"), CMElement("f") ]) ]),
                       L.Location("a buffer", -1)) ])
        @test (evaluate("<!ELEMENT a ((c,d)*,b,(e,f))>")
               == [ ED(false, "a", Sequence([ ZeroOrMore(Sequence([ CMElement("c"), CMElement("d") ])), CMElement("b"),
                                              Sequence([ CMElement("e"), CMElement("f") ])]),
                       L.Location("a buffer", -1)) ])
    end

    @testset "Events/Element Declarations, Element Content (Negative ... mixed combinators)" begin
        @test (evaluate("<!ELEMENT a (b|c,d)>")
               == [ ME("ERROR: '|' and ',' cannot be used in the same content group.", L.Location("a buffer", -1)),
                    ED(true, "a", Choice([ CMElement("b"), CMElement("c"), CMElement("d") ]), L.Location("a buffer", -1)) ])

        @test (evaluate("<!ELEMENT a (b,c|d)>")
               == [ ME("ERROR: '|' and ',' cannot be used in the same content group.", L.Location("a buffer", -1)),
                    ED(true, "a", Sequence([ CMElement("b"), CMElement("c"), CMElement("d") ]), L.Location("a buffer", -1)) ])
    end

    @testset "Events/Element Declarations, Element Content (Negative ... missing separator)" begin
        # We need to collect the first separator ... basically so that we know what to miss later on.
        #
        @test (evaluate("<!ELEMENT a (b|c d)>")
               == [ ME("ERROR: Expecting '|'.", L.Location("a buffer", -1)),
                    ED(true, "a", Choice([ CMElement("b"), CMElement("c"), CMElement("d") ]), L.Location("a buffer", -1)) ])

        @test (evaluate("<!ELEMENT a (b,c d)>")
               == [ ME("ERROR: Expecting ','.", L.Location("a buffer", -1)),
                    ED(true, "a", Sequence([ CMElement("b"), CMElement("c"), CMElement("d") ]), L.Location("a buffer", -1)) ])
    end

    @testset "Events/Element Declarations, Element Content (Negative ... missing element name or GRPO)" begin
        @test (evaluate("<!ELEMENT a (+)>")
               == [ ME("ERROR: Expecting an element name or '('.", L.Location("a buffer", -1)),
                    ME("ERROR: Expecting '>' to end an element declaration.", L.Location("a buffer", -1)),
                    ED(true, "a", CMAny(), L.Location("a buffer", -1)),
                    DC(")", false, L.Location("a buffer", -1)),
                    DC(">", false, L.Location("a buffer", -1)) ])
    end

    @testset "Events/Element Declarations, Element Content (Negative ... missing GRPC)" begin
        # Verify that a single-child element content model is handled properly. Assuming minimal white space for now.
        #
        @test (evaluate("<!ELEMENT a (b>")
               == [ ME("ERROR: Expecting ')' to end a content model group.", L.Location("a buffer", -1)),
                    ED(true, "a", CMElement("b"), L.Location("a buffer", -1)) ])

        @test (evaluate("<!ELEMENT a (b,(c>")
               == [ ME("ERROR: Expecting ')' to end a content model group.", L.Location("a buffer", -1)),
                    ME("ERROR: Expecting ','.", L.Location("a buffer", -1)),
                    ME("ERROR: Expecting an element name or '('.", L.Location("a buffer", -1)),
                    ME("ERROR: Expecting ')' to end a content model group.", L.Location("a buffer", -1)) ])
    end

    @testset "Events/Element Declarations (Negative ... miscellaneous)" begin
        @test (evaluate("<!ELEMENT+ a (#PCDATA)>")
               == [ ME("ERROR: White space is required following the 'ELEMENT' keyword.", L.Location("a buffer", -1)),
                    ME("ERROR: Expecting an element name.", L.Location("a buffer", -1)),
                    DC("+", false, L.Location("a buffer", -1)),
                    DC(" ", true, L.Location("a buffer", -1)),
                    DC("a", false, L.Location("a buffer", -1)),
                    DC(" ", true, L.Location("a buffer", -1)),
                    DC("(", false, L.Location("a buffer", -1)),
                    DC("#PCDATA", false, L.Location("a buffer", -1)),
                    DC(")", false, L.Location("a buffer", -1)),
                    DC(">", false, L.Location("a buffer", -1)), ])

        @test (evaluate("<!ELEMENT a b>")
               == [ ME("ERROR: Expecting 'ANY', 'EMPTY', or '(' to open a content model.", L.Location("a buffer", -1)),
                    ME("ERROR: Expecting '>' to end an element declaration.", L.Location("a buffer", -1)),
                    ED(true, "a", CMAny(), L.Location("a buffer", -1)),
                    DC(">", false, L.Location("a buffer", -1)), ])
    end
end

max_stars_repo_name: jlegare/NativeXML

max_issues_repo_name: jlegare/NativeXML

max_forks_repo_name: jlegare/NativeXML


text: println("hey")


text:
using Test
using LatexPrint
using Measurements
using DataFrames

@test latex_form(-5) == "-5"
@test latex_form(2.2) == "2.2"
@test latex_form("Hello") == "\\text{Hello}"
@test latex_form(-3//5) == "\\frac{-3}{5}"
@test latex_form(im) == "0+1i"
@test latex_form(1/0) == "\\infty"
@test latex_form(0/0) == "\\text{NaN}"
@test latex_form(pi) == "\\pi"
@test latex_form([1,2]) == "\\left[\n\\begin{array}{c}\n1 \\\\\n2 \\\\\n\\end{array}\n\\right]"
@test latex_form([1,2]') == "\\left[\n\\begin{array}{cc}\n1 & 2 \\\\\n\\end{array}\n\\right]"
@test latex_form(pi) == "\\pi"
@test latex_form(Set(1:4)) == "\\left\\{1,2,3,4\\right\\}"
@test latex_form(true) == "\\mathrm{T}"
@test latex_form(nothing) == "\\mathrm{nothing}"
@test latex_form(7.0±2.0) == "7.0\\pm 2.0"

io = IOBuffer()
df = DataFrame("Name" => ["A", "B"], "Score" => Any[6.1±1.3, π])
tabular(io, df)
str = String(take!(io))
@test str == "\\begin{tabular}{cc}\n\\hline\nName & Score\\\\ \\hline\n\\hline\n\$\\text{A}\$ & \$6.1\\pm 1.3\$\\\\\n\$\\text{B}\$ & \$\\pi\$\n\\end{tabular}\n"