text:
export BlankDynamics

mutable struct BlankDynamics <: DynamicsModel
  x_dim
  u_dim
end

BlankDynamics() = BlankDynamics(3,3)

function cost_true(traj, traj_prev::Trajectory, SCPP::SCPProblem{BlankRobot, BlankDynamics})
	0
end

function cost_true_convexified(traj, traj_prev::Trajectory, SCPP::SCPProblem{BlankRobot, BlankDynamics})
	cost_true(traj, traj_prev, SCPP)
end

macro blank_constraint(expr)
	return quote
		function (traj, traj_prev, SCPP)
			X, U, Tf = traj.X, traj.U, traj.Tf
			Xp, Up, Tfp = traj_prev.X, traj_prev.U, traj_prev.Tf
			robot, model, x_init, x_goal = SCPP.PD.robot, SCPP.PD.model, SCPP.PD.x_init, SCPP.PD.x_goal
			x_dim, u_dim, N = model.x_dim, model.u_dim, SCPP.N

			return (X, U, Tf, Tfp, robot, model, x_init, x_goal, x_dim, u_dim) -> $expr
		end
	end
end

function SCPConstraints(traj, traj_prev::Trajectory, SCPP::SCPProblem{BlankRobot, BlankDynamics})

	SCPC = SCPConstraints()

	# Dynamics constraints
	for k = 1:N-1
		push!(SCPC.dynamics, @blank_constraint X[1,k] + Tf*U[k] - X[1,k+1])
		push!(SCPC.dynamics, @blank_constraint X[2,k] + Tf*U[k] - X[2,k+1])
		push!(SCPC.dynamics, @blank_constraint X[3,k] + Tf*U[k] - X[3,k+1])
	end

	# Convex state constraints

	# Nonconvex state constraints

	# Nonconvex state constraints (convexified)

	# Convex control constraints

	return SCPC
end


text:
const CLP_SOLVER = ClpSolver()
const MAX_SENSE = -1.0
const MIN_SENSE = 1.0

## -------------------------------------------------------------------
function fba(S, b, lb, ub, c; solver = CLP_SOLVER)
    LP = linprog(
        c, # Opt sense vector
        S, # Stoichiometric matrix
        b, # row lb
        b, # row ub
        lb, # column lb
        ub, # column ub
        solver
    )
    return isempty(LP.sol) ? zeros(length(lb)) : LP.sol
end

function fba(S, b, lb, ub, c, idx, sense; kwargs...)
    bk_c = c[idx]
    c[idx] = sense
    try;
        sol = fba(S, b, lb, ub, c; kwargs...)
        return sol
    finally; c[idx] = bk_c end
end

## -------------------------------------------------------------------
function fva(S, b, lb, ub, c, idx::Integer;  kwargs...)
    bk_c = c[idx]
    c[idx] = MIN_SENSE
    try
        L = fba(S, b, lb, ub, c; kwargs...)[idx]
        c[idx] = MAX_SENSE
        U = fba(S, b, lb, ub, c; kwargs...)[idx]
        return (first(L), first(U))
    finally; c[idx] = bk_c end
end

function fva(S, b, lb, ub, c, idxs; kwargs...)
    L = zeros(length(idxs))
    U = zeros(length(idxs))
    for (i, idx) in idxs |> enumerate
        L[i], U[i] = fva(S, b, lb, ub, c, idx; kwargs...)
    end
    return (L, U)
end

ext: jl


text:
using Distributed: @everywhere, addprocs, remotecall_eval
addprocs(1)
@everywhere using LambdaTAME

@testset "distributed_drivers" begin

    trials = 1
    n_sizes = [50]

    @testset "pairwise alignment" begin

        betas = [0.0,1e1]
        alphas = [1.0,.5]
        iter=5
        primalDualTol=1e-5
        # -- check tensor alignment routines -- #
        @testset "Align ssten files " begin
            files = [tensor_A_file, tensor_B_file]
            path = "./"

            @suppress_out begin
                for profile in [true,false]
                    for method in [ΛTAME_M(),LowRankTAME_M(),TAME_M()]
                        if method === ΛTAME_M()
                            @inferred distributed_pairwise_alignment(files,path;method,iter=5, alphas, betas,
                                                                matchingMethod=ΛTAME_GramMatching(),profile,primalDualTol)
                            @test_nothrow distributed_pairwise_alignment(files,path;method,iter=5, alphas,betas,
                                                                matchingMethod=ΛTAME_GramMatching(),profile,primalDualTol)
                        elseif method === LowRankTAME_M() || method === TAME_M()
                            @inferred distributed_pairwise_alignment(files,path;method,iter, alphas,
                                                                     betas, profile, primalDualTol)
                            @test_nothrow distributed_pairwise_alignment(files,path;method, iter, alphas,
                                                                         betas,profile,primalDualTol)
                        end
                    end
                end
            end
        end

        @testset "Align smat files " begin
            @suppress_out begin
                files = [matrix_A_file, matrix_B_file]
                path = "./"

                samples=1000
                orders = [4]
                motif = LambdaTAME.Clique()
                        # Cycles are partially supported
                for profile in [true,false]
                    for postProcessing in [noPostProcessing(),KlauAlgo(maxiter=2),LocalSearch(iterations=2)]
                        for method in [ΛTAME_MultiMotif_M(),LowRankTAME_MultiMotif_M(),ΛTAME_M(),LowRankTAME_M(),LowRankEigenAlign_M()]
                            if method === ΛTAME_MultiMotif_M()

                                @inferred distributed_pairwise_alignment(files,path;method,profile,alphas,betas,primalDualTol,
                                                                                motif,samples,orders,postProcessing,
                                                                                matchingMethod=ΛTAME_GramMatching())
                                @test_nothrow distributed_pairwise_alignment(files,path;method,profile,alphas,betas,primalDualTol,
                                                                                motif,samples,orders,postProcessing,
                                                                                matchingMethod=ΛTAME_GramMatching())
                            elseif method === LowRankTAME_MultiMotif_M() || method === TAME_MultiMotif_M()
                                @inferred distributed_pairwise_alignment(files,path;method,iter,alphas,betas,profile,primalDualTol,
                                                                                motif,samples,orders,postProcessing)
                                @test_nothrow distributed_pairwise_alignment(files,path;method,iter,alphas,betas,profile,primalDualTol,
                                                                                motif,samples,orders,postProcessing)
                            elseif method === ΛTAME_M()
                                @inferred distributed_pairwise_alignment(files,path;method,iter, alphas, betas,postProcessing,
                                                                         matchingMethod=ΛTAME_GramMatching(),profile,primalDualTol)
                                @test_nothrow distributed_pairwise_alignment(files,path;method,iter, alphas, betas,postProcessing,
                                                                             matchingMethod=ΛTAME_GramMatching(),profile,primalDualTol)
                            elseif method === LowRankTAME_M()
                                @inferred distributed_pairwise_alignment(files,path;method,iter=5, alphas,postProcessing,
                                                                         betas,profile,primalDualTol)
                                @test_nothrow distributed_pairwise_alignment(files,path;method,iter, alphas,postProcessing,
                                                                             betas,profile,primalDualTol)
                            elseif method === LowRankEigenAlign_M()
                                @inferred distributed_pairwise_alignment(files,path;method,profile,postProcessing)
                                @test_nothrow distributed_pairwise_alignment(files,path;method,profile,postProcessing)
                            end
                        end
                    end
                    # -- TAME_M() doesn't support Post processing -- #
                    @inferred distributed_pairwise_alignment(files,path;method=TAME_M(),iter, alphas,
                                                            betas,profile,primalDualTol)
                    @test_nothrow distributed_pairwise_alignment(files,path;method=TAME_M(),iter, alphas,
                                                                 betas,profile,primalDualTol)
                    @inferred distributed_pairwise_alignment(files,path;method=TAME_MultiMotif_M(),iter,alphas,
                                                             motif,samples,orders,
                                                             betas,profile,primalDualTol)
                    @test_nothrow distributed_pairwise_alignment(files,path;method=TAME_MultiMotif_M(),iter, alphas,
                                                                 motif,samples,orders,
                                                                 betas,profile,primalDualTol)
                end
            end
        end

    end

    @testset "random_graphs" begin
        samples=10^4
        orders=[3]
        motif=LambdaTAME.Clique()
        primalDualTol=1e-5
        graph = RandomGeometric()
        @testset "Duplication Noise" begin
            edge_inclusion_p=[1.0]
            step_percentage=[.1]

            @suppress_out begin
                for postProcessing in [noPostProcessing(),KlauAlgo(maxiter=2),LocalSearch(iterations=2)]
                    for method in [ΛTAME_MultiMotif_M(),LowRankTAME_MultiMotif_M(),ΛTAME_M(),LowRankTAME_M(),LowRankEigenAlign_M()]

                        if method === ΛTAME_MultiMotif_M()

                            @inferred distributed_random_trials(trials,DuplicationNoise(),true; method, graph,
                                                    n_sizes, edge_inclusion_p, step_percentage,samples,orders,
                                                    matchingMethod=ΛTAME_GramMatching(),motif,primalDualTol,postProcessing)

                            @test_nothrow distributed_random_trials(trials,DuplicationNoise(),true; method, graph,
                                                    n_sizes, edge_inclusion_p, step_percentage,samples,orders,motif,
                                                    matchingMethod=ΛTAME_GramMatching(),primalDualTol,postProcessing)
                        elseif method === LowRankTAME_MultiMotif_M()
                            @inferred distributed_random_trials(trials,DuplicationNoise(),true; method, graph,
                                                                n_sizes, edge_inclusion_p, step_percentage,samples,orders,motif,
                                                                primalDualTol,postProcessing)

                            @test_nothrow distributed_random_trials(trials,DuplicationNoise(),true; method, graph,
                                                                    n_sizes, edge_inclusion_p, step_percentage,samples,orders,motif,
                                                                    primalDualTol,postProcessing)
                        elseif method === ΛTAME_M()
                            @inferred distributed_random_trials(trials,DuplicationNoise(),true; method, graph,
                                                    n_sizes, edge_inclusion_p, step_percentage,
                                                    matchingMethod=ΛTAME_GramMatching(),primalDualTol,postProcessing)
                            @test_nothrow distributed_random_trials(trials,DuplicationNoise(),true; method, graph,
                                                    n_sizes, edge_inclusion_p, step_percentage,
                                                    matchingMethod=ΛTAME_GramMatching(),primalDualTol,postProcessing)
                        elseif method === LowRankTAME_M()
                            @inferred distributed_random_trials(trials,DuplicationNoise(),true; method, graph,
                                                    n_sizes, edge_inclusion_p, step_percentage, primalDualTol,postProcessing)
                            @test_nothrow distributed_random_trials(trials,DuplicationNoise(),true; method, graph,
                                                    n_sizes, edge_inclusion_p, step_percentage, primalDualTol,postProcessing)
                        elseif method === LowRankEigenAlign_M()
                            @inferred distributed_random_trials(trials,DuplicationNoise(),true; method, graph,
                                                    n_sizes, edge_inclusion_p, step_percentage,postProcessing)
                            @test_nothrow distributed_random_trials(trials,DuplicationNoise(),true; method, graph,
                                                    n_sizes, edge_inclusion_p, step_percentage,postProcessing)
                        end
                    end
                end

                # -- TAME_M() doesn't support Post processing -- #
                @inferred distributed_random_trials(trials,DuplicationNoise(),true; method=TAME_M(), graph,
                                                    n_sizes, edge_inclusion_p, step_percentage,
                                                    primalDualTol)
                @test_nothrow distributed_random_trials(trials,DuplicationNoise(),true; method=TAME_M(), graph,
                                                        n_sizes, edge_inclusion_p, step_percentage,
                                                        primalDualTol)
                @inferred distributed_random_trials(trials,DuplicationNoise(),true; method=TAME_MultiMotif_M(), graph,
                                                    n_sizes, edge_inclusion_p, step_percentage,
                                                    samples,orders,motif, primalDualTol)
                @test_nothrow distributed_random_trials(trials,DuplicationNoise(),true; method=TAME_MultiMotif_M(), graph,
                                                        n_sizes, edge_inclusion_p, step_percentage,
                                                        samples,orders,motif, primalDualTol)
            end
        end

        @testset "Erdos Renyi Noise" begin
            p_remove = [.01]
            @suppress_out begin
                for postProcessing in [noPostProcessing(),KlauAlgo(maxiter=2),LocalSearch(iterations=2)]
                    for method in [ΛTAME_MultiMotif_M(),LowRankTAME_MultiMotif_M(),ΛTAME_M(),LowRankTAME_M(),LowRankEigenAlign_M()]

                        if method === ΛTAME_MultiMotif_M()
                            @inferred distributed_random_trials(trials,ErdosRenyiNoise(),true;method, graph,
                                                                n_sizes, p_remove, matchingMethod=ΛTAME_GramMatching(),
                                                                samples,orders,motif,primalDualTol,postProcessing)
                            @test_nothrow distributed_random_trials(trials,ErdosRenyiNoise(),true;method, graph,
                                                                n_sizes, p_remove, matchingMethod=ΛTAME_GramMatching(),
                                                                samples,orders,motif,primalDualTol,postProcessing)
                        elseif method === LowRankTAME_MultiMotif_M()
                            @inferred distributed_random_trials(trials,ErdosRenyiNoise(),true;method, graph,
                                                                n_sizes, p_remove, samples,orders,primalDualTol,
                                                                postProcessing, motif)
                            @test_nothrow distributed_random_trials(trials,ErdosRenyiNoise(),true;method, graph,
                                                                    n_sizes, p_remove, samples,orders,
                                                                    primalDualTol,postProcessing,motif)
                        elseif method === ΛTAME_M()
                            @inferred distributed_random_trials(trials,ErdosRenyiNoise(),true;method, graph,
                                                                n_sizes,p_remove, matchingMethod=ΛTAME_GramMatching(),
                                                                primalDualTol,postProcessing)
                            @test_nothrow distributed_random_trials(trials,ErdosRenyiNoise(),true;method, graph,
                                                                    n_sizes,p_remove, matchingMethod=ΛTAME_GramMatching(),
                                                                    primalDualTol,postProcessing)

                        elseif method === LowRankTAME_M()
                            @inferred distributed_random_trials(trials,ErdosRenyiNoise(),true; method, graph,
                                                                n_sizes, p_remove, primalDualTol,postProcessing)
                            @test_nothrow distributed_random_trials(trials,ErdosRenyiNoise(),true; method, graph,
                                                                    n_sizes, p_remove, primalDualTol,postProcessing)
                        elseif method === LowRankEigenAlign_M()
                            @inferred distributed_random_trials(trials,ErdosRenyiNoise(),true; method, graph,
                                                                n_sizes, p_remove,postProcessing)
                            @test_nothrow distributed_random_trials(trials,ErdosRenyiNoise(),true; method, graph,
                                                                    n_sizes, p_remove,postProcessing)
                        end
                    end
                end

                # -- TAME_M() doesn't support Post processing -- #

                @inferred distributed_random_trials(trials,ErdosRenyiNoise(),true; method=TAME_M(), graph,
                                                    n_sizes, p_remove,primalDualTol)
                @test_nothrow distributed_random_trials(trials,ErdosRenyiNoise(),true; method=TAME_M(), graph,
                                                        n_sizes, p_remove,primalDualTol)
                @inferred distributed_random_trials(trials,ErdosRenyiNoise(),true; method=TAME_MultiMotif_M(), graph,
                                                    n_sizes, p_remove,primalDualTol,samples,orders,motif)
                @test_nothrow distributed_random_trials(trials,ErdosRenyiNoise(),true; method=TAME_MultiMotif_M(), graph,
                                                        n_sizes, p_remove,primalDualTol,
                                                        samples,orders,motif)
            end
        end
    end

end

max_stars_repo_name: chuckcol/LambdaTAME

max_issues_repo_name: chuckcol/LambdaTAME

max_forks_repo_name: chuckcol/LambdaTAME


text:
# Test the basics
@testset "Basics" begin
    # setup data
    m = InfiniteModel()
    @infinite_parameter(m, a in [0, 1], derivative_method = TestMethod())
    @variable(m, x, Infinite(a))
    idx = DerivativeIndex(1)
    num = Float64(0)
    func = (x) -> NaN
    func2 = (a...) -> 1
    info = VariableInfo(false, num, false, num, false, num, false, func, false, false)
    new_info = VariableInfo(true, 0., true, 0., true, 0., true, func2, false, false)
    deriv = Derivative(info, true, x, a)
    deriv2 = Derivative(new_info, true, x, a)
    object = VariableData(deriv, "var")
    dref = DerivativeRef(m, idx)
    gvref = GeneralVariableRef(m, 1, DerivativeIndex)
    bad_dref = DerivativeRef(m, DerivativeIndex(-1))
    # JuMP.owner_model
    @testset "JuMP.owner_model" begin
        @test owner_model(dref) === m
        @test owner_model(gvref) === m
    end
    # JuMP.index
    @testset "JuMP.index" begin
        @test index(dref) == idx
        @test index(gvref) == idx
    end
    # dispatch_variable_ref
    @testset "dispatch_variable_ref" begin
        @test isequal(dispatch_variable_ref(m, idx), dref)
        @test isequal(dispatch_variable_ref(gvref), dref)
    end
    # _add_data_object
    @testset "_add_data_object" begin
        @test InfiniteOpt._add_data_object(m, object) == idx
    end
    # _data_dictionary
    @testset "_data_dictionary" begin
        @test InfiniteOpt._data_dictionary(m, Derivative) === m.derivatives
        @test InfiniteOpt._data_dictionary(dref) === m.derivatives
        @test InfiniteOpt._data_dictionary(gvref) === m.derivatives
    end
    # JuMP.is_valid
    @testset "JuMP.is_valid" begin
        @test is_valid(m, dref)
        @test is_valid(m, gvref)
    end
    # _data_object
    @testset "_data_object" begin
        @test InfiniteOpt._data_object(dref) === object
        @test InfiniteOpt._data_object(gvref) === object
        @test_throws ErrorException InfiniteOpt._data_object(bad_dref)
    end
    # _existing_derivative_index
    @testset "_existing_derivative_index" begin
        @test InfiniteOpt._existing_derivative_index(x, a) === nothing
        m.deriv_lookup[(x, a)] = idx
        @test InfiniteOpt._existing_derivative_index(x, a) === idx
    end
    # _core_variable_object
    @testset "_core_variable_object" begin
        @test InfiniteOpt._core_variable_object(dref) === deriv
        @test InfiniteOpt._core_variable_object(gvref) === deriv
    end
    # _set_core_variable_object
    @testset "_set_core_variable_object" begin
        @test InfiniteOpt._set_core_variable_object(dref, deriv) isa Nothing
        @test InfiniteOpt._set_core_variable_object(dref, deriv2) isa Nothing
        @test InfiniteOpt._set_core_variable_object(dref, deriv) isa Nothing
    end
    # _object_numbers
    @testset "_object_numbers" begin
        @test InfiniteOpt._object_numbers(dref) == [1]
    end
    # _parameter_numbers
    @testset "_parameter_numbers" begin
        @test InfiniteOpt._parameter_numbers(dref) == [1]
    end
    # test _variable_info
    @testset "_variable_info" begin
        @test InfiniteOpt._variable_info(dref) == info
    end
    # test _is_vector_start
    @testset "_is_vector_start" begin
        @test InfiniteOpt._is_vector_start(dref)
    end
    # _update_variable_info
    @testset "_update_variable_info" begin
        @test isa(InfiniteOpt._update_variable_info(dref, new_info), Nothing)
        @test InfiniteOpt._variable_info(dref) == new_info
    end
    # _measure_dependencies
    @testset "_measure_dependencies" begin
        @test InfiniteOpt._measure_dependencies(dref) == MeasureIndex[]
        @test InfiniteOpt._measure_dependencies(gvref) == MeasureIndex[]
    end
    # _constraint_dependencies
    @testset "_constraint_dependencies" begin
        @test InfiniteOpt._constraint_dependencies(dref) == InfOptConstraintIndex[]
        @test InfiniteOpt._constraint_dependencies(gvref) == InfOptConstraintIndex[]
    end
    # _semi_infinite_variable_dependencies
    @testset "_semi_infinite_variable_dependencies" begin
        @test InfiniteOpt._semi_infinite_variable_dependencies(dref) == SemiInfiniteVariableIndex[]
        @test InfiniteOpt._semi_infinite_variable_dependencies(gvref) == SemiInfiniteVariableIndex[]
    end
    # _point_variable_dependencies
    @testset "_point_variable_dependencies" begin
        @test InfiniteOpt._point_variable_dependencies(dref) == PointVariableIndex[]
        @test InfiniteOpt._point_variable_dependencies(gvref) == PointVariableIndex[]
    end
    # _derivative_dependencies
    @testset "_derivative_dependencies" begin
        @test InfiniteOpt._derivative_dependencies(dref) == DerivativeIndex[]
        @test InfiniteOpt._derivative_dependencies(gvref) == DerivativeIndex[]
    end
    # _derivative_constraint_dependencies
    @testset "_derivative_constraint_dependencies" begin
        @test InfiniteOpt._derivative_constraint_dependencies(dref) == InfOptConstraintIndex[]
        @test InfiniteOpt._derivative_constraint_dependencies(gvref) == InfOptConstraintIndex[]
    end
    # JuMP.name
    @testset "JuMP.name" begin
        @test name(dref) == "var"
        @test name(gvref) == "var"
        @test name(bad_dref) == ""
    end
    # JuMP.set_name
    @testset "JuMP.set_name" begin
        # test default
        @test isa(set_name(dref, ""), Nothing)
        @test name(dref) == ""
        @test_throws ErrorException set_name(bad_dref, "")
        # test normal
        @test isa(set_name(gvref, "new"), Nothing)
        @test name(dref) == "new"
    end
    # derivative_argument
    @testset "derivative_argument" begin
        @test isequal(derivative_argument(dref), x)
        @test isequal(derivative_argument(gvref), x)
    end
    # operator_parameter
    @testset "operator_parameter" begin
        @test isequal(operator_parameter(dref), a)
        @test isequal(operator_parameter(gvref), a)
    end
    # derivative_method
    @testset "derivative_method" begin
        @test derivative_method(dref) == TestMethod()
        @test derivative_method(gvref) == TestMethod()
    end
    # set_derivative_method
    @testset "set_derivative_method" begin
        @test_throws ErrorException set_derivative_method(dref, TestGenMethod())
        @test_throws ErrorException set_derivative_method(gvref, TestGenMethod())
    end
    # raw_parameter_refs
    @testset "raw_parameter_refs" begin
        @test isequal(raw_parameter_refs(dref), IC.VectorTuple(a))
        @test isequal(raw_parameter_refs(gvref), IC.VectorTuple(a))
    end
    # parameter_refs
    @testset "parameter_refs" begin
        @test isequal(parameter_refs(dref), (a, ))
        @test isequal(parameter_refs(gvref), (a, ))
    end
    # parameter_list
    @testset "parameter_list" begin
        @test isequal(parameter_list(dref), [a])
        @test isequal(parameter_list(gvref), [a])
    end
    # _make_variable_ref
    @testset "_make_variable_ref" begin
        @test isequal(InfiniteOpt._make_variable_ref(m, idx), gvref)
    end
    # _var_name_dict
    @testset "_var_name_dict" begin
        @test InfiniteOpt._var_name_dict(m) isa Nothing
    end
    # test has_derivative_constraints
    @testset "has_derivative_constraints" begin
        @test !has_derivative_constraints(dref)
    end
    # _delete_data_object
    @testset "_delete_data_object" begin
        @test InfiniteOpt._delete_data_object(dref) isa Nothing
        @test length(InfiniteOpt._data_dictionary(dref)) == 0
        @test !is_valid(m, dref)
    end
end

# Test variable definition methods
@testset "Definition" begin
    # initialize model and infinite variable info
    m = InfiniteModel()
    @infinite_parameter(m, pref in [0, 1])
    @infinite_parameter(m, pref2 in [0, 1])
    @infinite_parameter(m, prefs[1:2] in [0, 1])
    @finite_parameter(m, fin == 42)
    @variable(m, x, Infinite(pref, prefs))
    @variable(m, y, Infinite(pref2))
    num = Float64(0)
    func1 = (a, b) -> 2
    info = VariableInfo(false, num, false, num, false, num, false, NaN, false, false)
    info2 = VariableInfo(true, num, true, num, true, num, true, func1, false, false)
    info3 = VariableInfo(true, num, true, num, true, num, true, 42, false, true)
    info4 = VariableInfo(true, num, false, num, false, num, false, s -> NaN, false, false)
    # build_derivative
    @testset "build_derivative" begin
        # test errors
        @test_throws ErrorException build_derivative(error, info, y, fin)
        @test_throws ErrorException build_derivative(error, info, y, pref)
        @test_throws ErrorException build_derivative(error, info, pref, pref)
        func = (a, b, c) -> a + sum(c)
        bad_info = VariableInfo(true, num, true, num, true, num, true, func, false, false)
        @test_throws ErrorException build_derivative(error, bad_info, x, pref)
        # test for expected output
        @test build_derivative(error, info, x, pref).info isa VariableInfo
        @test build_derivative(error, info, x, pref).is_vector_start
        @test isequal(build_derivative(error, info, x, pref).variable_ref, x)
        @test isequal(build_derivative(error, info, x, pref).parameter_ref, pref)
    end
    # Deriv{V, P}
    @testset "Deriv{V, P}" begin
        @test isequal(Deriv(x, pref).argument, x)
        @test isequal(Deriv(x, pref).operator_parameter, pref)
    end
    # build_variable
    @testset "JuMP.build_variable" begin
        # test for each error message
        @test_throws ErrorException build_variable(error, info, Deriv(x, prefs[1]),
                                                   bob = 42)
        @test_throws ErrorException build_variable(error, info, Deriv(0, prefs[1]))
        @test_throws ErrorException build_variable(error, info, Deriv(x, 0))
        # test for expected output
        @test build_variable(error, info, Deriv(x, prefs[1])) isa Derivative
    end
    # add_derivative
    @testset "add_derivative" begin
        # prepare secondary model and parameter and variable
        m2 = InfiniteModel()
        @infinite_parameter(m2, pref3 in [0, 1])
        @variable(m2, z, Infinite(pref3))
        d = build_derivative(error, info, z, pref3)
        # test for error of invalid variable
        @test_throws VariableNotOwned{InfiniteVariableRef} add_derivative(m, d)
        # prepare normal variable
        d = build_derivative(error, info, x, pref)
        # test normal
        idx = DerivativeIndex(1)
        dref = DerivativeRef(m, idx)
        gvref = InfiniteOpt._make_variable_ref(m, idx)
        @test isequal(add_derivative(m, d, "name"), gvref)
        @test haskey(InfiniteOpt._data_dictionary(dref), idx)
        @test InfiniteOpt._core_variable_object(dref) == d
        @test InfiniteOpt._derivative_dependencies(pref) == [idx]
        @test InfiniteOpt._derivative_dependencies(x) == [idx]
        @test name(dref) == "name"
        @test InfiniteOpt._existing_derivative_index(x, pref) == idx
        # prepare infinite variable with all the possible info additions
        d = build_derivative(error, info2, x, prefs[1])
        # test info addition functions
        idx = DerivativeIndex(2)
        dref = DerivativeRef(m, idx)
        gvref = InfiniteOpt._make_variable_ref(m, idx)
        @test isequal(add_derivative(m, d, "name"), gvref)
        @test !optimizer_model_ready(m)
        @test InfiniteOpt._derivative_dependencies(prefs[1]) == [idx]
        @test InfiniteOpt._derivative_dependencies(x) == [DerivativeIndex(i) for i = 1:2]
        @test !InfiniteOpt._is_vector_start(dref)
        @test InfiniteOpt._variable_info(dref).start == func1
        @test InfiniteOpt._existing_derivative_index(x, prefs[1]) == idx
        # lower bound
        cindex = InfOptConstraintIndex(1)
        cref = InfOptConstraintRef(m, cindex)
        @test has_lower_bound(dref)
        @test InfiniteOpt._lower_bound_index(dref) == cindex
        @test constraint_object(cref) isa ScalarConstraint{GeneralVariableRef,
                                                           MOI.GreaterThan{Float64}}
        @test InfiniteOpt._data_object(cref).is_info_constraint
        # upper bound
        cindex = InfOptConstraintIndex(2)
        cref = InfOptConstraintRef(m, cindex)
        @test has_upper_bound(dref)
        @test InfiniteOpt._upper_bound_index(dref) == cindex
        @test constraint_object(cref) isa ScalarConstraint{GeneralVariableRef,
                                                           MOI.LessThan{Float64}}
        @test InfiniteOpt._data_object(cref).is_info_constraint
        # fix
        cindex = InfOptConstraintIndex(3)
        cref = InfOptConstraintRef(m, cindex)
        @test is_fixed(dref)
        @test InfiniteOpt._fix_index(dref) == cindex
        @test constraint_object(cref) isa ScalarConstraint{GeneralVariableRef,
                                                           MOI.EqualTo{Float64}}
        @test InfiniteOpt._data_object(cref).is_info_constraint
        @test InfiniteOpt._constraint_dependencies(dref) == [InfOptConstraintIndex(i)
                                                             for i = 1:3]
        # test redundant build
        idx = DerivativeIndex(1)
        dref = DerivativeRef(m, idx)
        gvref = InfiniteOpt._make_variable_ref(m, idx)
        d = Derivative(info4, true, x, pref)
        @test isequal(add_derivative(m, d, "name2"), gvref)
        @test haskey(InfiniteOpt._data_dictionary(dref), idx)
        @test InfiniteOpt._core_variable_object(dref) == d
        @test name(dref) == "name2"
        @test lower_bound(dref) == 0
    end
    # test JuMP.add_variable
    @testset "JuMP.add_variable" begin
        # prepare normal variable
        d = build_derivative(error, info, x, prefs[2])
        # test normal
        idx = DerivativeIndex(3)
        dref = DerivativeRef(m, idx)
        gvref = InfiniteOpt._make_variable_ref(m, idx)
        @test isequal(add_variable(m, d, "name"), gvref)
        @test haskey(InfiniteOpt._data_dictionary(dref), idx)
        @test InfiniteOpt._core_variable_object(dref) == d
        @test InfiniteOpt._derivative_dependencies(prefs[2]) == [idx]
        @test InfiniteOpt._derivative_dependencies(x) == [DerivativeIndex(i) for i = 1:3]
        @test name(dref) == "name"
        @test InfiniteOpt._existing_derivative_index(x, prefs[2]) == idx
    end
    # test "_build_deriv_expr (GeneralVariableRef)"
    @testset "_build_deriv_expr (GeneralVariableRef)" begin
        # test with same parameters
        @test InfiniteOpt._build_deriv_expr(pref, pref) == 1
        @test InfiniteOpt._build_deriv_expr(prefs[2], prefs[2]) == 1
        # test with new derivative
        gvref = GeneralVariableRef(m, 4, DerivativeIndex)
        @test isequal(InfiniteOpt._build_deriv_expr(y, pref2), gvref)
        # test returning existing derivative
        @test isequal(InfiniteOpt._build_deriv_expr(y, pref2), gvref)
        # test others
        @test InfiniteOpt._build_deriv_expr(pref, pref2) == 0
        @test InfiniteOpt._build_deriv_expr(fin, pref2) == 0
        @test InfiniteOpt._build_deriv_expr(x, pref2) == 0
    end
    # test "_build_deriv_expr (AffExpr)"
    @testset "_build_deriv_expr (AffExpr)" begin
        @test InfiniteOpt._build_deriv_expr(2x+42, pref2) == 0
        @test InfiniteOpt._build_deriv_expr(2pref2 - 23, pref2) == 2
        gvref = GeneralVariableRef(m, 1, DerivativeIndex)
        @test isequal(InfiniteOpt._build_deriv_expr(-4x, pref), -4gvref)
    end
    # test "_build_deriv_expr (QuadExpr)"
    @testset "_build_deriv_expr (QuadExpr)" begin
        @test isequal(InfiniteOpt._build_deriv_expr(2x^2 + 42, pref2), @expression(m, 0*x))
        @test isequal(InfiniteOpt._build_deriv_expr(2pref2^2 -pref2 - 23, pref2), 4pref2 - 1)
        gvref = GeneralVariableRef(m, 1, DerivativeIndex)
        @test isequal(InfiniteOpt._build_deriv_expr(-4x^2, pref), -8 * gvref * x)
    end
    # test "_build_deriv_expr (Number)"
    @testset "_build_deriv_expr (Number)" begin
        @test InfiniteOpt._build_deriv_expr(42, pref2) == 0
    end
    # test "_build_deriv_expr (Fallback)"
    @testset "_build_deriv_expr (Fallback)" begin
        @test_throws ErrorException InfiniteOpt._build_deriv_expr("bob", pref2)
    end
    # test "_recursive_deriv_build"
    @testset "_recursive_deriv_build" begin
        @test InfiniteOpt._recursive_deriv_build(2pref^2 + pref, [pref, pref]) == 4
        @test InfiniteOpt._recursive_deriv_build(2pref^2 + pref, [pref, pref2]) == 0.
        gvref = GeneralVariableRef(m, 5, DerivativeIndex)
        @test isequal(InfiniteOpt._recursive_deriv_build(x + pref, [pref, pref]), gvref + 0)
    end
    # test "deriv"
    @testset "deriv" begin
        # test errors
        @test_throws ErrorException deriv(x, pref, fin)
        @test_throws ErrorException deriv(x)
        # test normal
        gvref = GeneralVariableRef(m, 1, DerivativeIndex)
        @test isequal(deriv(x, pref), gvref)
        @test deriv(pref, pref) == 1
        @test isequal_canonical(deriv(x^2 + pref, pref), 2 * gvref * x + 1)
        @test deriv(pref^2, pref, pref) == 2
        @test deriv(pref^2, pref, pref, pref) == 0
        @test deriv(42, pref, pref) == 0
    end
    # test "∂"
    @testset "∂" begin
        # test errors
        @test_throws ErrorException ∂(x, pref, fin)
        @test_throws ErrorException ∂(x)
        # test normal
        gvref = GeneralVariableRef(m, 1, DerivativeIndex)
        @test isequal(∂(x, pref), gvref)
        @test ∂(pref, pref) == 1
        @test isequal_canonical(∂(x^2 + pref, pref), 2 * gvref * x + 1)
        @test ∂(pref^2, pref, pref) == 2
        @test ∂(pref^2, pref, pref, pref) == 0
        @test ∂(42, pref, pref) == 0
    end
    # test "@deriv"
    @testset "@deriv" begin
        # test errors
        @test_throws ErrorException @deriv(x, pref, fin)
        @test_throws ErrorException @deriv(x)
        @test_macro_throws ErrorException @deriv(x, pref, bad = 1)
        # test normal
        gvref = GeneralVariableRef(m, 1, DerivativeIndex)
        gvref2 = GeneralVariableRef(m, 5, DerivativeIndex)
        @test isequal(@deriv(x, pref), gvref)
        @test @deriv(pref, pref) == 1
        @test isequal_canonical(@deriv(x^2, pref^2), 2 * gvref2 * x + 2gvref^2)
        @test @deriv(pref^2, pref^2) == 2
        @test @deriv(pref^2, pref^3) == 0
        @test @deriv(42, pref^1) == 0
        @test @deriv(x, pref^2, prefs[2]) isa GeneralVariableRef
        # test with semi_infinite variables
        rv = build_variable(error, gvref, Dict{Int, Float64}(1 => 0.))
        rvref = add_variable(m, rv)
        @test @deriv(rvref, prefs[1]) isa GeneralVariableRef
        # test with measures
        meas = Measure(y, TestData(pref, 0, 1), [3], [3, 4], false)
        data = MeasureData(meas, "meas")
        @test InfiniteOpt._add_data_object(m, data) isa MeasureIndex
        mref = GeneralVariableRef(m, 1, MeasureIndex)
        @test @deriv(mref, prefs[2]) isa GeneralVariableRef
    end
    # test "@∂"
    @testset "@∂" begin
        # test errors
        @test_throws ErrorException @∂(x, pref, fin)
        @test_throws ErrorException @∂(x)
        # test normal
        gvref = GeneralVariableRef(m, 1, DerivativeIndex)
        gvref2 = GeneralVariableRef(m, 5, DerivativeIndex)
        @test isequal(@∂(x, pref), gvref)
        @test @∂(pref, pref) == 1
        @test isequal_canonical(@∂(x^2, pref^2), 2 * gvref2 * x + 2gvref^2)
        @test @∂(pref^2, pref^2) == 2
        @test @∂(pref^2, pref^3) == 0
        @test @∂(42, pref^1) == 0
        @test @∂(x, pref^2, prefs[2]) isa GeneralVariableRef
    end
end

# Test the info methods
@testset "Info Methods" begin
    m = InfiniteModel()
    @infinite_parameter(m, t in [0, 1])
    @variable(m, x, Infinite(t))
    @variable(m, dx >= 0, Deriv(x, t))
    # test lower bound stuff
    @testset "Lower Bound Methods" begin
        @test has_lower_bound(dx)
        @test lower_bound(dx) == 0
        @test LowerBoundRef(dx) isa InfOptConstraintRef
        @test set_lower_bound(dx, 2) isa Nothing
        @test lower_bound(dx) == 2
    end
    # test upper bound stuff
    @testset "Upper Bound Methods" begin
        @test !has_upper_bound(dx)
        @test set_upper_bound(dx, 10) isa Nothing
        @test upper_bound(dx) == 10
        @test UpperBoundRef(dx) isa InfOptConstraintRef
    end
    # test fix stuff
    @testset "Fix Methods" begin
        @test !is_fixed(dx)
        @test fix(dx, 42, force = true) isa Nothing
        @test fix_value(dx) == 42
        @test FixRef(dx) isa InfOptConstraintRef
    end
end

# Test Start Methods
@testset "Start Value" begin
    # initialize model and 4 test variables
    m = InfiniteModel()
    @infinite_parameter(m, t in [0, 1])
    @variable(m, inf, Infinite(t))
    @variable(m, d1, Deriv(inf, t), start = 0)
    @variable(m, d2, Deriv(d1, t))
    dref = dispatch_variable_ref(d1)
    # start_value
    @testset "JuMP.start_value" begin
        @test_throws ErrorException start_value(d1)
        @test_throws ErrorException start_value(dref)
    end
    # set_start_value
    @testset "JuMP.set_start_value" begin
        @test_throws ErrorException set_start_value(d1, 0)
        @test_throws ErrorException set_start_value(dref, 0)
    end
    # start_value_function
    @testset "start_value_function" begin
        @test start_value_function(d1)([1]) == 0
        @test start_value_function(dref)([1]) == 0
        @test InfiniteOpt._is_vector_start(dref)
        @test start_value_function(d2) isa Nothing
    end
    # set_start_value_function
    @testset "set_start_value_function" begin
        @test set_start_value_function(d1, 1.5) isa Nothing
        @test start_value_function(d1)([0]) == 1.5
        @test InfiniteOpt._is_vector_start(dref)
        @test !optimizer_model_ready(m)
        func = (a) -> 1
        @test set_start_value_function(d1, func) isa Nothing
        @test start_value_function(d1)(0) == 1
        @test !InfiniteOpt._is_vector_start(dref)
    end
    # reset_start_value_function
    @testset "reset_start_value_function" begin
        @test reset_start_value_function(d1) isa Nothing
        @test start_value_function(d1) isa Nothing
        @test InfiniteOpt._is_vector_start(dref)
        @test !optimizer_model_ready(m)
    end
end

# Test Macro Definition
@testset "Macro Definition" begin
    # initialize model and stuff
    m = InfiniteModel()
    @infinite_parameter(m, t in [0, 1])
    @infinite_parameter(m, x[1:2] in [-1, 1])
    @variable(m, y, Infinite(t, x))
    @variable(m, q[1:3], Infinite(t, x))
    # test single variable definition
    @testset "Single" begin
        # test simple anon case
        idx = DerivativeIndex(1)
        dref = DerivativeRef(m, idx)
        gvref = InfiniteOpt._make_variable_ref(m, idx)
        @test isequal(@variable(m, variable_type = Deriv(y, t)), gvref)
        @test isequal(derivative_argument(dref), y)
        @test isequal(operator_parameter(dref), t)
        # test anon with changes to fixed
        idx = DerivativeIndex(2)
        dref = DerivativeRef(m, idx)
        gvref = InfiniteOpt._make_variable_ref(m, idx)
        @test isequal(@variable(m, variable_type = Deriv(y, x[1]), lower_bound = -5,
                        upper_bound = 10, start = 2), gvref)
        @test isequal(derivative_argument(dref), y)
        @test isequal(operator_parameter(dref), x[1])
        @test lower_bound(dref) == -5
        @test upper_bound(dref) == 10
        @test start_value_function(dref) isa Function
        # test regular with alias
        idx = DerivativeIndex(1)
        dref = DerivativeRef(m, idx)
        gvref = InfiniteOpt._make_variable_ref(m, idx)
        @test isequal(@variable(m, dx <= 0, Deriv(y, t)), gvref)
        @test isequal(derivative_argument(dref), y)
        @test isequal(operator_parameter(dref), t)
        @test used_by_derivative(y)
        @test used_by_derivative(t)
        @test upper_bound(dref) == 0
        @test name(dref) == "dx"
    end
    # test array variable definition
    @testset "Array" begin
        # test anon array with one parameter
        idxs = [DerivativeIndex(3), DerivativeIndex(4)]
        drefs = [DerivativeRef(m, idx) for idx in idxs]
        gvrefs = [InfiniteOpt._make_variable_ref(m, idx) for idx in idxs]
        @test isequal(@variable(m, [i = 1:2], Deriv(q[i], t), lower_bound = 0), gvrefs)
        @test isequal(derivative_argument(drefs[1]), q[1])
        @test isequal(operator_parameter(drefs[2]), t)
        @test lower_bound(drefs[2]) == 0
        # test explicit array
        idxs = [DerivativeIndex(5), DerivativeIndex(6)]
        drefs = [DerivativeRef(m, idx) for idx in idxs]
        gvrefs = [InfiniteOpt._make_variable_ref(m, idx) for idx in idxs]
        @test isequal(@variable(m, q4[i = 1:2] == 3, Deriv(q[i+1], x[i])), gvrefs)
        @test isequal(derivative_argument(drefs[1]), q[2])
        @test isequal(operator_parameter(drefs[2]), x[2])
        @test fix_value(drefs[2]) == 3
        @test name(drefs[1]) == "q4[1]"
        # test semi anon array
        idxs = [DerivativeIndex(7), DerivativeIndex(8)]
        drefs = [DerivativeRef(m, idx) for idx in idxs]
        gvrefs = [InfiniteOpt._make_variable_ref(m, idx) for idx in idxs]
        @test isequal(@variable(m, [i = 1:2], Deriv(q[i], x[i]), lower_bound = -5), gvrefs)
        @test isequal(derivative_argument(drefs[2]), q[2])
        @test isequal(operator_parameter(drefs[1]), x[1])
        @test lower_bound(drefs[2]) == -5
        @test name(drefs[1]) == ""
    end
    # test errors
    @testset "Errors" begin
        # test same name error
        @test_macro_throws ErrorException @variable(m, y, Deriv(y, t))
    end
end

# test usage methods
@testset "Usage" begin
    # initialize model and stuff
    m = InfiniteModel()
    @infinite_parameter(m, t in [0, 1])
    @infinite_parameter(m, x[1:2] in [-1, 1])
    @variable(m, y, Infinite(t, x))
    d = @deriv(y, t)
    vref = dispatch_variable_ref(d)
    # test used_by_semi_infinite_variable
    @testset "used_by_semi_infinite_variable" begin
        @test !used_by_semi_infinite_variable(vref)
        push!(InfiniteOpt._semi_infinite_variable_dependencies(vref),
              SemiInfiniteVariableIndex(1))
        @test used_by_semi_infinite_variable(d)
        @test used_by_semi_infinite_variable(vref)
        empty!(InfiniteOpt._semi_infinite_variable_dependencies(vref))
    end
    # test used_by_point_variable
    @testset "used_by_point_variable" begin
        @test !used_by_point_variable(vref)
        push!(InfiniteOpt._point_variable_dependencies(vref), PointVariableIndex(1))
        @test used_by_point_variable(d)
        @test used_by_point_variable(vref)
        empty!(InfiniteOpt._point_variable_dependencies(vref))
    end
    # test used_by_derivative
    @testset "used_by_derivative" begin
        @test !used_by_derivative(vref)
        push!(InfiniteOpt._derivative_dependencies(vref), DerivativeIndex(1))
        @test used_by_derivative(d)
        @test used_by_derivative(vref)
        empty!(InfiniteOpt._derivative_dependencies(vref))
    end
    # test used_by_measure
    @testset "used_by_measure" begin
        @test !used_by_measure(vref)
        push!(InfiniteOpt._measure_dependencies(vref), MeasureIndex(1))
        @test used_by_measure(d)
        @test used_by_measure(vref)
        empty!(InfiniteOpt._measure_dependencies(vref))
    end
    # test used_by_constraint
    @testset "used_by_constraint" begin
        @test !used_by_constraint(vref)
        push!(InfiniteOpt._constraint_dependencies(vref), InfOptConstraintIndex(1))
        @test used_by_constraint(d)
        @test used_by_constraint(vref)
        empty!(InfiniteOpt._constraint_dependencies(vref))
    end
    # test used_by_objective
    @testset "used_by_objective" begin
        @test !used_by_objective(d)
        @test !used_by_objective(vref)
    end
    # test is_used
    @testset "is_used" begin
        # test not used
        @test !is_used(vref)
        # test used by constraint and/or measure
        push!(InfiniteOpt._constraint_dependencies(vref), InfOptConstraintIndex(1))
        @test is_used(d)
        empty!(InfiniteOpt._constraint_dependencies(vref))
        # test used by point variable
        num = Float64(0)
        info = VariableInfo(false, num, false, num, false, num, false, num, false, false)
        var = PointVariable(info, d, [0., 0., 0.])
        object = VariableData(var, "var")
        idx = PointVariableIndex(1)
        pvref = PointVariableRef(m, idx)
        @test InfiniteOpt._add_data_object(m, object) == idx
        push!(InfiniteOpt._point_variable_dependencies(vref), idx)
        @test !is_used(vref)
        push!(InfiniteOpt._constraint_dependencies(pvref), InfOptConstraintIndex(2))
        @test is_used(vref)
        empty!(InfiniteOpt._point_variable_dependencies(vref))
        # test used by semi_infinite variable
        eval_supps = Dict{Int, Float64}(1 => 0.5, 3 => 1)
        var = SemiInfiniteVariable(d, eval_supps, [2], [2])
        object = VariableData(var, "var")
        idx = SemiInfiniteVariableIndex(1)
        rvref = SemiInfiniteVariableRef(m, idx)
        @test InfiniteOpt._add_data_object(m, object) == idx
        push!(InfiniteOpt._semi_infinite_variable_dependencies(vref), idx)
        @test !is_used(vref)
        push!(InfiniteOpt._constraint_dependencies(rvref), InfOptConstraintIndex(2))
        @test is_used(vref)
        empty!(InfiniteOpt._semi_infinite_variable_dependencies(vref))
        # test used by derivative
        func = (x) -> NaN
        num = 0.
        info = VariableInfo{Float64, Float64, Float64, Function}(true, num, true,
                                         num, true, num, false, func, true, true)
        d2 = @deriv(d, t)
        dref = DerivativeRef(m, index(d2))
        push!(InfiniteOpt._derivative_dependencies(vref), index(d2))
        @test !is_used(vref)
        push!(InfiniteOpt._constraint_dependencies(dref), InfOptConstraintIndex(2))
        @test is_used(vref)
        empty!(InfiniteOpt._derivative_dependencies(vref))
    end
end

# Test General Queries
@testset "Other Queries" begin
    # setup
    m = InfiniteModel()
    @infinite_parameter(m, t in [0, 1])
    @infinite_parameter(m, x[1:2] in [0, 1])
    @variable(m, y, Infinite(t, x))
    d1 = @deriv(y, t)
    d2 = @deriv(y, x[1])
    d3 = @deriv(d2, t)
    cref = @constraint(m, d1 == 0)
    push!(InfiniteOpt._derivative_constraint_dependencies(d1), index(cref))
    InfiniteOpt._set_has_derivative_constraints(t, true)
    # test num_derivatives
    @testset "num_derivative" begin
        @test num_derivatives(m) == 3
    end
    # test all_derivatives
    @testset "all_derivative" begin
        @test isequal(all_derivatives(m), [d1, d2, d3])
    end
    # test derivative_constraints
    @testset "derivative_constraints" begin
        @test derivative_constraints(d1) == [cref]
    end
    # test delete_derivative_constraints
    @testset "delete_derivative_constraints" begin
        @test delete_derivative_constraints(d1) isa Nothing
        @test !has_derivative_constraints(d1)
        @test !has_derivative_constraints(t)
        @test !is_valid(m, cref)
    end
end

# Test the definition of semi-infinite and point derivatives
@testset "Semi-Infinite/Point Derivatives" begin
    # setup
    m = InfiniteModel()
    @infinite_parameter(m, t in [0, 1])
    @infinite_parameter(m, x[1:2] in [0, 1])
    @variable(m, y, Infinite(t, x))
    d = @deriv(y, t)
    # test semi-infinite derivatives
    @testset "Semi-infinite Derivatives" begin
        dref = GeneralVariableRef(m, 1, SemiInfiniteVariableIndex)
        @test isequal(@variable(m, variable_type = SemiInfinite(d, 1, x)), dref)
        @test isequal(parameter_refs(dref), (x,))
        @test isequal(infinite_variable_ref(dref), d)
        @test eval_supports(dref)[1] == 1
    end
    # test point derivatives
    @testset "Point Derivatives" begin
        dref = GeneralVariableRef(m, 1, PointVariableIndex)
        @test isequal(@variable(m, variable_type = Point(d, 0, [0, 0])), dref)
        @test parameter_refs(dref) == ()
        @test isequal(infinite_variable_ref(dref), d)
        @test parameter_values(dref) == (0, [0, 0])
    end
    # test using restrict
    @testset "Restriction Definition" begin
        # test semi-infinite
        dref = GeneralVariableRef(m, 2, SemiInfiniteVariableIndex)
        @test isequal(restrict(d, 0, x), dref)
        @test isequal(parameter_refs(dref), (x,))
        @test isequal(infinite_variable_ref(dref), d)
        @test eval_supports(dref)[1] == 0
        # test point
        dref = GeneralVariableRef(m, 2, PointVariableIndex)
        @test isequal(d(1, [0, 0]), dref)
        @test parameter_refs(dref) == ()
        @test isequal(infinite_variable_ref(dref), d)
        @test parameter_values(dref) == (1, [0, 0])
    end
end


text:
################################################################################
# Forward-backward splitting iterator
#
# This iterator implements the algorithms ISTA (when fast=False) and FISTA
# (when fast=True) described in
# [1] Beck, Teboulle "A Fast Iterative Shrinkage-Thresholding Algorithm for Linear Inverse Problems," SIAM Journal on Imaging Sciences vol. 2, no. 1, pp. 183-202 (2009)
# or equivalently (when fast=True) Algorithm 2 described in
# [2] Tseng, "On Accelerated Proximal Gradient Methods for Convex-Concave Optimization," (2008)
#

mutable struct FBSIterator{I <: Integer, R <: Real, D, CS, FS, AS, CQ, FQ, AQ, G} <: ProximalAlgorithm{I, D}
    x::D
    fs::FS
    As::AS
    fq::FQ
    Aq::AQ
    g::G
    gamma::R
    maxit::I
    tol::R
    adaptive::Bool
    fast::Bool
    verbose::I
    verbose_freq::I
    theta::R # extrapolation parameter
    y::D # gradient step
    z::D # proximal-gradient step
    z_prev::D
    FPR_x::D
    Aqx::CQ
    Asx::CS
    Aqz::CQ
    Asz::CS
    gradfq_Aqx::CQ
    gradfs_Asx::CS
    Aqt_gradfq_Aqx::D
    Ast_gradfs_Asx::D
    fs_Asx::R
    fq_Aqx::R
    f_Ax::R
    At_gradf_Ax::D
    Aqz_prev::CQ
    Asz_prev::CS
    gradfq_Aqz::CQ
    gradfs_Asz::CS
    gradfq_Aqz_prev::CQ
end

################################################################################
# Constructor

function FBSIterator(x0::D;
                     fs::FS=Zero(), As::AS=Identity(size(x0)),
                     fq::FQ=Zero(), Aq::AQ=Identity(size(x0)),
                     g::G=Zero(),
                     gamma::R=-1.0, maxit::I=10000, tol::R=1e-4,
                     adaptive::Bool=false, fast::Bool=false,
                     verbose::I=1, verbose_freq::I = 100) where {I, R, D, FS, AS, FQ, AQ, G}
    x = copy(x0)
    y = zero(x0)
    z = zero(x0)
    z_prev = zero(x0)
    FPR_x = zero(x0)
    Aqx = Aq*x
    Asx = As*x
    Aqz = zero(Aqx)
    Asz = zero(Asx)
    gradfq_Aqx = zero(Aqx)
    gradfs_Asx = zero(Asx)
    Aqt_gradfq_Aqx = zero(x0)
    Ast_gradfs_Asx = zero(x0)
    At_gradf_Ax = zero(x0)
    Aqz_prev = zero(Aqx)
    Asz_prev = zero(Asx)
    gradfq_Aqz = zero(Aqx)
    gradfs_Asz = zero(Asx)
    gradfq_Aqz_prev = zero(Aqx)
    CQ = typeof(Aqx)
    CS = typeof(Asx)
    FBSIterator{I, R, D, CS, FS, AS, CQ, FQ, AQ, G}(x,
             fs, As, fq, Aq, g,
             gamma, maxit, tol, adaptive, fast, verbose, verbose_freq, 1.0,
             y, z, z_prev, FPR_x,
             Aqx, Asx,
             Aqz, Asz,
             gradfq_Aqx, gradfs_Asx,
             Aqt_gradfq_Aqx, Ast_gradfs_Asx,
             0.0, 0.0, 0.0,
             At_gradf_Ax, Aqz_prev,
             Asz_prev,
             gradfq_Aqz, gradfs_Asz, gradfq_Aqz_prev)
end

################################################################################
# Utility methods

maxit(sol::FBSIterator{I}) where {I} = sol.maxit

converged(sol::FBSIterator{I, R, D}, it::I) where {I, R, D}  = it > 0 && maximum(abs,sol.FPR_x)/sol.gamma <= sol.tol

verbose(sol::FBSIterator) = sol.verbose > 0
verbose(sol::FBSIterator, it) = sol.verbose > 0 && (sol.verbose == 2 ? true : (it == 1 || it%sol.verbose_freq == 0))

function display(sol::FBSIterator)
    @printf("%6s | %10s | %10s |\n ", "it", "gamma", "fpr")
    @printf("------|------------|------------|\n")
end

function display(sol::FBSIterator, it)
    @printf("%6d | %7.4e | %7.4e |\n", it, sol.gamma, maximum(abs,sol.FPR_x)/sol.gamma)
end

function Base.show(io::IO, sol::FBSIterator)
    println(io, (sol.fast ? "Fast " : "")*"Forward-Backward Splitting" )
    println(io, "fpr        : $(maximum(abs,sol.FPR_x))")
    print(  io, "gamma      : $(sol.gamma)")
end

################################################################################
# Initialization

function initialize!(sol::FBSIterator{I, R, D, CS, FS, AS, CQ, FQ, AQ, G}) where {I, R, D, CS, FS, AS, CQ, FQ, AQ, G}

    # reset parameters
    sol.theta = 1.0

    # compute first forward-backward step here
    mul!(sol.Aqx, sol.Aq, sol.x)
    sol.fq_Aqx = gradient!(sol.gradfq_Aqx, sol.fq, sol.Aqx)
    mul!(sol.Asx, sol.As, sol.x)
    sol.fs_Asx = gradient!(sol.gradfs_Asx, sol.fs, sol.Asx)
    mul!(sol.Ast_gradfs_Asx, sol.As', sol.gradfs_Asx)
    mul!(sol.Aqt_gradfq_Aqx, sol.Aq', sol.gradfq_Aqx)
    sol.At_gradf_Ax .= sol.Ast_gradfs_Asx .+ sol.Aqt_gradfq_Aqx
    sol.f_Ax = sol.fs_Asx + sol.fq_Aqx

    if sol.gamma <= 0.0 # estimate L in this case, and set gamma = 1/L
        # this part should be as follows:
        # 1) if adaptive = false and only fq is present then L is "accurate"
        # 2) otherwise L is "inaccurate" and set adaptive = true
        # TODO: implement case 1), now 2) is always performed
        xeps = sol.x .+ sqrt(eps())
        Aqxeps = sol.Aq*xeps
        gradfq_Aqxeps, = gradient(sol.fq, Aqxeps)
        Asxeps = sol.As*xeps
        gradfs_Asxeps, = gradient(sol.fs, Asxeps)
        At_gradf_Axeps = sol.As'*gradfs_Asxeps .+ sol.Aq'*gradfq_Aqxeps
        L = norm(sol.At_gradf_Ax .- At_gradf_Axeps)/(sqrt(eps()*length(xeps)))
        sol.adaptive = true
        # in both cases set gamma = 1/L
        sol.gamma = 1.0/L
    end

    sol.y .= sol.x .- sol.gamma .* sol.At_gradf_Ax
    prox!(sol.z, sol.g, sol.y, sol.gamma)
    sol.FPR_x .= sol.x .- sol.z

    return sol.z
end

################################################################################
# Iteration

function iterate!(sol::FBSIterator{I, R, D, CS, FS, AS, CQ, FQ, AQ, G}, it::I) where {I, R, D, CS, FS, AS, CQ, FQ, AQ, G}

    fq_Aqz = zero(R)
    fs_Asz = zero(R)

    if sol.adaptive
        for it_gam = 1:100 # TODO: replace/complement with lower bound on gamma
            normFPR_x = norm(sol.FPR_x)
            uppbnd = sol.f_Ax - real(dot(sol.At_gradf_Ax, sol.FPR_x)) + 0.5/sol.gamma*normFPR_x^2
            mul!(sol.Aqz, sol.Aq, sol.z)
            fq_Aqz = gradient!(sol.gradfq_Aqz, sol.fq, sol.Aqz)
            mul!(sol.Asz, sol.As, sol.z)
            fs_Asz = gradient!(sol.gradfs_Asz, sol.fs, sol.Asz)
            f_Az = fs_Asz + fq_Aqz
            if f_Az > uppbnd + 1e-6*abs(sol.f_Ax)
                sol.gamma = 0.5*sol.gamma
                sol.y .= sol.x - sol.gamma .* sol.At_gradf_Ax
                prox!(sol.z, sol.g, sol.y, sol.gamma)
                sol.FPR_x .= sol.x .- sol.z
            else
                break
            end
        end
    end

    if sol.fast == false
        sol.x, sol.z = sol.z, sol.x
        if sol.adaptive == true
            sol.Aqx, sol.Aqz = sol.Aqz, sol.Aqx
            sol.fq_Aqx = fq_Aqz
            sol.gradfq_Aqx, sol.gradfq_Aqz = sol.gradfq_Aqz, sol.gradfq_Aqx
            sol.Asx, sol.Asz = sol.Asz, sol.Asx
            sol.fs_Asx = fs_Asz
            sol.gradfs_Asx, sol.gradfs_Asz = sol.gradfs_Asz, sol.gradfs_Asx
            mul!(sol.Ast_gradfs_Asx, sol.As', sol.gradfs_Asx)
            mul!(sol.Aqt_gradfq_Aqx, sol.Aq', sol.gradfq_Aqx)
            sol.At_gradf_Ax .= sol.Ast_gradfs_Asx .+ sol.Aqt_gradfq_Aqx
            sol.f_Ax = sol.fs_Asx + sol.fq_Aqx
        end
    else
        # compute extrapolation coefficient
        theta1 = (1.0+sqrt(1.0+4*sol.theta^2))/2.0
        extr = (sol.theta - 1.0)/theta1
        sol.theta = theta1
        # perform extrapolation
        sol.x .= sol.z .+ extr.*(sol.z .- sol.z_prev)

        sol.z, sol.z_prev = sol.z_prev, sol.z
        if sol.adaptive == true
            # extrapolate other extrapolable quantities
            sol.Aqx .= sol.Aqz .- sol.Aqz_prev
            sol.gradfq_Aqx .= sol.gradfq_Aqz .- sol.gradfq_Aqz_prev
            coeff_linear = real(dot(sol.gradfq_Aqz, sol.Aqx))
            coeff_quadr = real(dot(sol.Aqx, sol.gradfq_Aqx))
            sol.fq_Aqx = fq_Aqz + extr*coeff_linear + 0.5*coeff_quadr*extr^2
            sol.Aqx .= sol.Aqz .+ extr.*(sol.Aqz .- sol.Aqz_prev)
            sol.gradfq_Aqx .= sol.gradfq_Aqz .+ extr.*(sol.gradfq_Aqz .- sol.gradfq_Aqz_prev)
            sol.Asx .= sol.Asz .+ extr .*(sol.Asz .- sol.Asz_prev)
            # store the z-quantities for future extrapolation
            sol.Aqz_prev, sol.Aqz = sol.Aqz, sol.Aqz_prev
            sol.gradfq_Aqz_prev, sol.gradfq_Aqz = sol.gradfq_Aqz, sol.gradfq_Aqz_prev
            sol.Asz_prev, sol.Asz = sol.Asz, sol.Asz_prev
            # compute gradient of fs
            sol.fs_Asx = gradient!(sol.gradfs_Asx, sol.fs, sol.Asx)
            mul!(sol.Ast_gradfs_Asx, sol.As', sol.gradfs_Asx)
            # TODO: we can probably save the MATVEC by Aq' in the next line
            mul!(sol.Aqt_gradfq_Aqx, sol.Aq', sol.gradfq_Aqx)
            sol.At_gradf_Ax .= sol.Ast_gradfs_Asx .+ sol.Aqt_gradfq_Aqx
            sol.f_Ax = sol.fs_Asx + sol.fq_Aqx
        end
    end
    if sol.adaptive == false
        mul!(sol.Aqx, sol.Aq, sol.x)
        sol.fq_Aqx = gradient!(sol.gradfq_Aqx, sol.fq, sol.Aqx)
        mul!(sol.Asx, sol.As, sol.x)
        sol.fs_Asx = gradient!(sol.gradfs_Asx, sol.fs, sol.Asx)
        mul!(sol.Ast_gradfs_Asx, sol.As', sol.gradfs_Asx)
        mul!(sol.Aqt_gradfq_Aqx, sol.Aq', sol.gradfq_Aqx)
        sol.At_gradf_Ax .= sol.Ast_gradfs_Asx .+ sol.Aqt_gradfq_Aqx
        sol.f_Ax = sol.fs_Asx + sol.fq_Aqx
    end
    sol.y .= sol.x .- sol.gamma .* sol.At_gradf_Ax
    prox!(sol.z, sol.g, sol.y, sol.gamma)
    sol.FPR_x .= sol.x .- sol.z

    return sol.z

end

################################################################################
# Solver interface

"""
**Forward-backward splitting**

    FBS(x0; kwargs...)

Solves a problem of the form

    minimize fs(As*x) + fq(Aq*x) + g(x)

where `fs` is a smooth function, `fq` is a quadratic function, `g` is a
proximable function and `As`, `Aq` are linear operators. Parameter `x0` is the
initial point. Keyword arguments specify the problem and
additional options as follows:
* `fs`, smooth function (default: identically zero function)
* `fq`, quadratic function (default: identically zero function)
* `g`, proximable function (default: identically zero function)
* `As`, linear operator (default: identity)
* `Aq`, linear operator (default: identity)
* `gamma`, stepsize (default: unspecified, determine automatically)
* `maxit`, maximum number of iteration (default: `10000`)
* `tol`, halting tolerance on the fixed-point residual (default: `1e-4`)
* `adaptive`, adaptively adjust `gamma` (default: `false` if `gamma` is provided)
* `fast`, enables accelerated method (default: `false`)
* `verbose`, verbosity level (default: `1`)
* `verbose_freq`, verbosity frequency for `verbose = 1` (default: `100`)
"""
function FBS(x0; kwargs...)
    sol = FBSIterator(x0; kwargs...)
    it, point = run!(sol)
    return (it, point, sol)
end


text:
function testpostgres()
    PostgresType = PostgreSQL.PostgresType
    conn = connect(Postgres, "localhost", "postgres", "", "julia_test")
    run(conn, """CREATE TEMPORARY TABLE foobar (foo INTEGER PRIMARY KEY, bar DOUBLE PRECISION,
        foobar CHARACTER VARYING);""")
    stmt = prepare(conn, "INSERT INTO foobar (foo, bar, foobar) VALUES (\$1, \$2, \$3);")
    @test isempty(stmt.paramtypes)  # now that prepared statements are not being created
end

testpostgres()

max_stars_repo_name: beffaCo/updatePostgresql

max_forks_repo_name: beffaCo/updatePostgresql


text:
#!/usr/bin/env julia

include("ecef.jl")

function ecef2enu(x::Real, y::Real, z::Real, lat0::Real, lon0::Real, h0::Real, ell::Ellipsoid)
    #=
    input
    -----
    x,y,z  [meters] target ECEF location                             [0,Infinity)
    Observer: lat0, lon0, h0 (altitude, meters)
    ell    reference ellipsoid

    output:
    -------
    e,n,u   East, North, Up [m]
    =#

    x0, y0, z0 = geodetic2ecef(lat0, lon0, h0, ell)

    return uvw2enu(x - x0, y - y0, z - z0, lat0, lon0)
end

function uvw2enu(u::Real, v::Real, w::Real, lat0::Real, lon0::Real)

    lat0 = deg2rad(lat0)
    lon0 = deg2rad(lon0)

    t = cos(lon0) * u + sin(lon0) * v
    East = -sin(lon0) * u + cos(lon0) * v
    Up = cos(lat0) * t + sin(lat0) * w
    North = -sin(lat0) * t + cos(lat0) * w

    return (East, North, Up)
end

function aer2enu(az::Real, el::Real, srange::Real)
    #=
    input:
    ------
    azimuth, elevation (degrees/radians)                             [0,360),[0,90]
    slant range [meters]                                             [0,Infinity)
    deg    degrees input/output  (False: radians in/out)

    output:
    -------
    e,n,u   East, North, Up [m]

    =#

    el = deg2rad(el)
    az = deg2rad(az)

    r = srange * cos(el)

    return (r * sin(az), r * cos(az), srange * sin(el))
end

if basename(PROGRAM_FILE) == basename(@__FILE__)

  if length(ARGS) == 6

  else
    ell = Ellipsoid(6378137., 1 / 298.2572235630, 6378137. * (1 - 1 / 298.2572235630))

    lla0 = (42., -82., 200.)
    aer0 = (33., 70., 1000.)
    xyz = (660930.1927610816, -4.701424222957011e6, 4.246579604632881e6)
    east0, north0, up0 = (186.277521, 286.842228, 939.692621)

    east, north, up = ecef2enu(xyz..., lla0..., ell)

    @test isapprox(east, east0)
    @test isapprox(north, north0)
    @test isapprox(up, up0)

  end
end


text:
# import Base.Multimedia.display

struct RjuliaDisplay <: Display
    mime_dict:: Dict
end

## This function taken from IJulia
israwtext(::MIME, x::AbstractString) = true
israwtext(::MIME"text/plain", x::AbstractString) = false
israwtext(::MIME, x) = false

## This function taken from IJulia
# convert x to a string of type mime, making sure to use an
# IOContext that tells the underlying show function to limit output
function limitstringmime(mime::MIME, x)
    buf = IOBuffer()
    if istextmime(mime)
        if israwtext(mime, x)
            return String(x)
        else
            Base.invokelatest(show, IOContext(buf, :limit=>true), mime, x)
        end
    else
        b64 = Base64EncodePipe(buf)
        if isa(x, Vector{UInt8})
            write(b64, x) # x assumed to be raw binary data
        else
            show(IOContext(b64, :limit=>true), mime, x)
        end
        close(b64)
    end
    return String(take!(buf))
end

function display(display::RjuliaDisplay, m::MIME, x)
    s = limitstringmime(m, x)
    display_method = RCall.reval(display.mime_dict[string(m)])
    display_method(s)
end

function display(d::RjuliaDisplay, p)
    for m in ["text/html", "image/png", "image/jpeg", "application/pdf", "image/svg+xml",
        "text/markdown", "text/latex", "application/javascript", "text/plain"]
        try
            display(d, m, p)
            return
        catch e;
        end
    end
    throw(MethodError)
end

const irjulia_dict = Dict()

irjulia_dict["application/json"] = "IRdisplay::display_json"
irjulia_dict["application/javascript"] = "IRdisplay::display_javascript"
irjulia_dict["text/html"] = "function(x) IRdisplay::display_html(JuliaCall:::p_ly(JuliaCall:::html_wrap(x)))"
irjulia_dict["text/plain"] = "IRdisplay::display_html"
irjulia_dict["text/markdown"] =  "IRdisplay::display_markdown"
irjulia_dict["text/latex"] = "IRdisplay::display_latex"
irjulia_dict["image/png"] = "function(x) IRdisplay::display_png(charToRaw(x))"
irjulia_dict["image/jpeg"] = "function(x) IRdisplay::display_jpeg(charToRaw(x))"
irjulia_dict["application/pdf"] = "function(x) IRdisplay::display_pdf(charToRaw(x))"
irjulia_dict["image/svg+xml"] = "function(x) IRdisplay::display_svg(JuliaCall:::p_ly(x))"

const irjulia_display = RjuliaDisplay(irjulia_dict)

max_stars_repo_name: KevCaz/JuliaCall

max_issues_repo_name: KevCaz/JuliaCall

max_forks_repo_name: KevCaz/JuliaCall


text:
abstract type MomentEquations end

# TODO: implement getters

"""
$(TYPEDEF)

Raw moment equations generated for the given system plus a number of
helper parameters (used internally).

# Fields
$(FIELDS)
"""
struct RawMomentEquations <: MomentEquations
    """[`ModelingToolkit.ODESystem`](https://mtk.sciml.ai/stable/systems/ODESystem/)
    consisting of the time-evolution equations of raw moments."""
    odes::ODESystem
    """Symbolic variables defining the raw moments."""
    μ::OrderedDict
    """Number of species within the system."""
    N::Int
    """Order of moment equations."""
    m_order::Int
    """Expansion order."""
    q_order::Int
    """Vector of all index combinations up to `q_order`."""
    iter_all::Vector
    """Vector of all index combinations up to `m_order`."""
    iter_m::Vector
    """Vector of all index combinations of order greater than `m_order`
    up to `q_order`."""
    iter_q::Vector
    """Vector of index combinations of order 1."""
    iter_1::Vector
end

"""
$(TYPEDEF)

Central moment equations generated for the given system plus a number of
helper parameters (used internally).

# Fields
$(FIELDS)
"""
struct CentralMomentEquations <: MomentEquations
    """[`ModelingToolkit.ODESystem`](https://mtk.sciml.ai/stable/systems/ODESystem/)
    consisting of the time-evolution equations of central moments."""
    odes::ODESystem
    """Symbolic variables defining the means."""
    μ::OrderedDict
    """Symbolic variables defining the central moments."""
    M::Dict
    """Number of species within the system."""
    N::Int
    """Order of moment equations."""
    m_order::Int
    """Expansion order."""
    q_order::Int
    """Vector of all index combinations up to `q_order`."""
    iter_all::Vector
    """Vector of all index combinations up to `m_order`."""
    iter_m::Vector
    """Vector of all index combinations of order greater than `m_order`
    up to `q_order`."""
    iter_q::Vector
    """Vector of index combinations of order 1."""
    iter_1::Vector
end

"""
$(TYPEDEF)

Closed moment equations and the corresponding closure functions.

# Fields
$(FIELDS)
"""
struct ClosedMomentEquations <: MomentEquations
    """[`ModelingToolkit.ODESystem`](https://mtk.sciml.ai/stable/systems/ODESystem/)
    consisting of the time-evolution equations of *closed* moments."""
    odes::ODESystem
    """Dictionary of moment closure functions for each higher order moment."""
    closure::OrderedDict
    """Original raw or central moment equations (before closure was applied)."""
    open_eqs::MomentEquations
end

# a basic wrapper
function SciMLBase.ODEProblem(eqs::MomentEquations, args...; kwargs...)
    ODEProblem(eqs.odes, args...; kwargs...)
end

function Base.nameof(eqs::MomentEquations)
    nameof(eqs.odes)
end


text:
using HybridArrays, ArrayInterface, Test, StaticArrays
using ArrayInterface: StaticInt

@testset "ArrayInterface compatibility" begin
    M = HybridMatrix{2, StaticArrays.Dynamic()}([1 2; 4 5])
    MV = HybridMatrix{3, StaticArrays.Dynamic()}(view(randn(10, 10), 1:2:5, 1:3:12))
    @test ArrayInterface.ismutable(M)
    @test ArrayInterface.can_setindex(M)
    @test ArrayInterface.parent_type(M) === Matrix{Int}
    @test ArrayInterface.restructure(M, [2, 4, 6, 8]) == HybridMatrix{2, StaticArrays.Dynamic()}([2 6; 4 8])
    @test isa(ArrayInterface.restructure(M, [2, 4, 6, 8]), HybridMatrix{2, StaticArrays.Dynamic()})

    M2 = HybridArray{Tuple{2, 3, StaticArrays.Dynamic(), StaticArrays.Dynamic()}}(randn(2, 3, 5, 7))
    @test (@inferred ArrayInterface.strides(M2)) === (StaticInt(1), StaticInt(2), StaticInt(6), 30)
    @test (@inferred ArrayInterface.strides(MV)) === (2, 30)
    @test (@inferred ArrayInterface.size(M2)) === (StaticInt(2), StaticInt(3), 5, 7)

    @test ArrayInterface.contiguous_axis(typeof(M2)) === ArrayInterface.contiguous_axis(typeof(parent(M2)))
    @test ArrayInterface.contiguous_batch_size(typeof(M2)) === ArrayInterface.contiguous_batch_size(typeof(parent(M2)))
    @test ArrayInterface.stride_rank(typeof(M2)) === ArrayInterface.stride_rank(typeof(parent(M2)))
    @test ArrayInterface.contiguous_axis(typeof(M')) === ArrayInterface.contiguous_axis(typeof(parent(M)'))
    @test ArrayInterface.contiguous_batch_size(typeof(M')) === ArrayInterface.contiguous_batch_size(typeof(parent(M)'))
    @test ArrayInterface.stride_rank(typeof(M')) === ArrayInterface.stride_rank(typeof(parent(M)'))
end


text:
module Tutor

using Test
using Dates

end

# End of module


text:
#
# This file is part of module
#   ModiaMedia (ModiaMedia/src/ModiaMedia.jl)
#

### Data structures that are additionally available for media <: PartialMixtureMedium -----------------------

"""
    R = gasConstant(state)

Return gas constant of MixtureMedium from
`state::MixtureThermodynamicState` in [J/mol.K]
"""
gasConstant(medium::MixtureMedium, state::MixtureThermodynamicState) = undefinedFunction("gasConstant", state)
gasConstant(                       state::MixtureThermodynamicState) = gasConstant(state.medium,state)

# moleToMassFractions: use inner constructor with fluid information.
# massToMoleFractions: use inner constructor with fluid information from abstract medium, since we have that type.


text:
# =====================================
# Structs to work with waiting lists
# =====================================

"""
    StateInLocation{ST, M<:Integer}

Struct that associates a set with a hybrid automaton's location index,
usually an integer.
"""
struct StateInLocation{ST, M}
    X::ST     # set representation
    loc_id::M # discrete location index
end

state(s::StateInLocation) = s.X
location(s::StateInLocation) = s.loc_id

# convert to a struct with broader type
function Base.convert(::Type{StateInLocation{ST, M}}, s::StateInLocation{WT, M}) where {ST, WT<:ST, M}
    StateInLocation{ST, M}(s.X, s.loc_id)
end

# ===============================================================
# Abstract interface
# ===============================================================

"""
    AbstractWaitingList

Abstract supertype for all waiting list types.
"""
abstract type AbstractWaitingList end

# iterator interface
# array(w) should return the array of StateInLocation elements
@inline Base.getindex(w::AbstractWaitingList, i::Int) = getindex(array(w), i)
@inline Base.getindex(w::AbstractWaitingList, i::Number) = getindex(array(w), convert(Int, i))
@inline Base.getindex(w::AbstractWaitingList, I::AbstractVector) = getindex(array(w), I)
@inline Base.isempty(w::AbstractWaitingList) = isempty(array(w))
@inline Base.iterate(w::AbstractWaitingList) = iterate(array(w))
@inline Base.iterate(w::AbstractWaitingList, state) = iterate(array(w), state)
@inline Base.length(w::AbstractWaitingList) = length(array(w))
@inline Base.size(w::AbstractWaitingList) = (length(array(w)),)
@inline Base.first(w::AbstractWaitingList) = getindex(w, 1)
@inline Base.last(w::AbstractWaitingList) = getindex(w, lastindex(w))
@inline Base.firstindex(w::AbstractWaitingList) = 1
@inline Base.lastindex(w::AbstractWaitingList) = length(array(w))
@inline Base.eachindex(w::AbstractWaitingList) = eachindex(array(w))

# ===============================================================
# Waiting list with all sets of the same type
# ===============================================================

"""
    WaitingList{TN, ST, M, QT<:StateInLocation{ST, M}} <: AbstractWaitingList

Iterable container representing a list of pairs `(set, mode)` of a hybrid automaton.

### Fields

- `times`  -- vector with a time interval associated to each state
- `array`  -- vector of `StateInLocation`

### Notes

A `WaitingList` is a list of pairs ``(set_i, loc_i)` for `i in 1..k` where
`times` is a vector with a time interval associated to each state.

This waiting list allows for a unique set representation (`ST`) for all elements
of the list.
"""
struct WaitingList{TN, ST, M, QT<:StateInLocation{ST, M}} <: AbstractWaitingList
    times::Vector{TN}
    array::Vector{QT}

    function WaitingList(times::Vector{TN}, array::Vector{QT}) where {TN, ST, M, QT<:StateInLocation{ST, M}}
        @assert length(times) == length(array) || throw(ArgumentError("the lengths of the time " *
        "stamps and the array of sets should match, but they are $(length(times)) and $(length(array)) respectively"))

        return new{TN, ST, M, QT}(times, array)
    end
end

# constructor of empty waiting list
WaitingList{TN, ST, M}() where {TN, ST, M} = WaitingList(Vector{TN}(), Vector{StateInLocation{ST, M}}())
WaitingList{TN, ST, M, QT}() where {TN, ST, M, QT<:StateInLocation{ST, M}} = WaitingList(Vector{TN}(), Vector{QT}())

# constructor without time-stamp
WaitingList(array::Vector{QT}) where {ST, M, QT<:StateInLocation{ST, M}} = WaitingList{TimeInterval}(array)
function WaitingList{TN}(array::Vector{QT}) where {TN, ST, M, QT<:StateInLocation{ST, M}}
    times = fill(zeroI, length(array))
    WaitingList(times, array)
end

# getter functions
@inline array(w::WaitingList) = w.array
@inline times(w::WaitingList) = w.times
setrep(w::WaitingList{TN, ST}) where {TN, ST} = ST
locrep(w::WaitingList{TN, ST, M}) where {TN, ST, M} = M
tspan(w::WaitingList, i) = w.times[i]

# we let elem::ET be possibly different than QT, for waiting lists which mixed set representations
@inline function Base.push!(w::WaitingList{TN, ST, M, QT}, elem::ET) where {TN, ST, M, QT, ET}
    push!(w.times, zeroI)
    push!(w.array, elem)
    return w
end
@inline function Base.push!(w::WaitingList{TN, ST, M, QT}, Δt::TN, elem::ET) where {TN, ST, M, QT, ET}
    push!(w.times, Δt)
    push!(w.array, elem)
    return w
end

@inline Base.pop!(w::WaitingList) = (pop!(w.times), pop!(w.array))

# containment check
function Base.:⊆(s::StateInLocation, w::WaitingList)
    contained = false
    q = location(s)
    X = state(s)
    for elem in w
        if (location(elem) == q) && (X ⊆ state(elem))
            contained = true
            break
        end
    end
    return contained
end

# conversion from vector-of-tuples to waiting list
function Base.convert(::Type{TW}, Q::Vector{Tuple{M, ST}}) where {TW<:WaitingList, M<:Integer, ST<:AdmissibleSet}
    waiting_list = TW()
    for Qi in Q # no intersection chcks
        q, Xi = Qi
        push!(waiting_list, StateInLocation(Xi, q))
    end
    return waiting_list
end

# "duck-typing" conversion from vector-of-tuples to waiting list
function Base.convert(::Type{TW}, Q::Vector{Tuple{ST, M}}) where {TW<:WaitingList, ST<:AdmissibleSet, M<:Integer}
    waiting_list = TW()
    for Qi in Q # no intersection chcks
        Xi, q = Qi
        push!(waiting_list, StateInLocation(Xi, q))
    end
    return waiting_list
end

# ===============================================================
# Waiting list allowing storage of sets of different types
# ===============================================================

# non-strictly typed waiting list, useful for cases in which the set reprsentation
# to be added in the list is not known a priori
struct MixedWaitingList{TN, QT<:StateInLocation} <: AbstractWaitingList
    times::Vector{TN}
    array::Vector{QT}

    function MixedWaitingList(times::Vector{TN}, array::Vector{QT}) where {TN, QT<:StateInLocation}
        @assert length(times) == length(array) || throw(ArgumentError("the lengths of the time " *
        "stamps and the array of sets should match, but they are $(length(times)) and $(length(array)) respectively"))

        return new{TN, QT}(times, array)
    end
end

# constructor of empty waiting list
MixedWaitingList{TN, QT}() where {TN, QT} = MixedWaitingList(Vector{TN}(), Vector{StateInLocation}())


text:
#=
Write an algorithm to justify text. Given a sequence of words and an integer line length k, return a list of strings which represents each line, fully justified.

More specifically, you should have as many words as possible in each line. There should be at least one space between each word. Pad extra spaces when necessary so that each line has exactly length k. Spaces should be distributed as equally as possible, with the extra spaces, if any, distributed starting from the left.

If you can only fit one word on a line, then you should pad the right-hand side with spaces.

Each word is guaranteed not to be longer than k.

For example, given the list of words ["the", "quick", "brown", "fox", "jumps", "over", "the", "lazy", "dog"] and k = 16, you should return the following:

["the  quick brown", # 1 extra space on the left
"fox  jumps  over", # 2 extra spaces distributed evenly
"the   lazy   dog"] # 4 extra spaces distributed evenly
=#

using Test
include("Solutions/problem28_justifytext.jl")

@test justify(["the", "quick", "brown", "fox", "jumps", "over", "the", "lazy", "dog"], 16) == ["the  quick brown", "fox  jumps  over", "the   lazy   dog"]

max_stars_repo_name: DominiqueCaron/daily-coding-problem

max_issues_repo_name: DominiqueCaron/daily-coding-problem

max_forks_repo_name: DominiqueCaron/daily-coding-problem


text:
module ExtendedVariantModeRecoverJumpRefill

using ..Ahorn, Maple

@mapdef Entity "ExtendedVariantMode/RecoverJumpRefill" RecoverJumpRefill(x::Integer, y::Integer, oneUse::Bool=false, texture::String="ExtendedVariantMode/jumprefill", respawnTime::Number=2.5)
@mapdef Entity "ExtendedVariantMode/JumpRefill" LegacyJumpRefill(x::Integer, y::Integer, oneUse::Bool=false, texture::String="ExtendedVariantMode/jumprefill")

recoverJumpRefills = Union{RecoverJumpRefill, LegacyJumpRefill}

const placements = Ahorn.PlacementDict(
    "Recover Jump Refill (Extended Variant Mode)" => Ahorn.EntityPlacement(
        RecoverJumpRefill
    )
)

function Ahorn.selection(entity::recoverJumpRefills)
    sprite = "objects/" * get(entity.data, "texture", "ExtendedVariantMode/jumprefill") * "/idle00"
    x, y = Ahorn.position(entity)
    return Ahorn.getSpriteRectangle(sprite, x, y)
end

function Ahorn.render(ctx::Ahorn.Cairo.CairoContext, entity::recoverJumpRefills, room::Maple.Room)
    sprite = "objects/" * get(entity.data, "texture", "ExtendedVariantMode/jumprefill") * "/idle00"
    Ahorn.drawSprite(ctx, sprite, 0, 0)
end

end

max_stars_repo_name: Kokasgui/Everest-ExtendedVariants

max_issues_repo_name: Kokasgui/Everest-ExtendedVariants

max_forks_repo_name: Kokasgui/Everest-ExtendedVariants


text:
# # Примеры
#
# На этой странице мы делаем `include` примеров,
# которые лежат в корневом каталоге пакета в папке `"examples/"`.
#
# [Literate.jl](https://github.com/fredrikekre/Literate.jl) включает
# текст этих примеров и в md файл.
#
#src `#src` это комментарии даже для Literate.jl
#src `#md` Строки Literate.jl включит только в md файлы.
#
#src Перед всматриванием в следующий блок, посмотри `docs/make.jl`.
#src Там, скормив этот скрипт Literate.jl мы получим страницу
#src `docexample_direct.md`. Именно её будет обрабатывать Documenter.jl
#
#md # ```@contents
#md # Pages = [ "docexample_direct.md" ]
#md # Depth = 5
#md # ```

include("examples/example_direct.jl")

# ### Визуализация

# Мы не можем строить большие анимации на стороне `Travis`-a.
# Если мы на CI, то будем рисовать только 10 кадров.
# Если мы генерируем документацию локально, то рисуем 80 кадров.
isTravis = in("Travis", keys(ENV))
ftw = isTravis ? range(1, stop = M+1, length=9) : [1; 2:div(M+1, 80):M+1];

## Запись gif одного только решения
make_gif(u, XX, Tₘ; name="solution_direct_ex1.gif", frames_to_write = ftw)

## Запись **только** mp4 вместе с вырожденными корнями и переходным слоем.
make_gif(u, XX, Tₘ, ϕl, ϕr, ϕ, f1_data, f2_data;
         name="solution_direct_ex11.mp4", frames_to_write = ftw)

include("examples/example_direct_dparams.jl")

# ### Визуализация
# Так выглядит решение для стандартных данных.
make_gif(u, XX, Tₘ, ϕl, ϕr, ϕ, f1_data, f2_data; name="solution_direct_ex2.gif", frames_to_write = ftw)

include("examples/example_direct_nonuniform.jl")

# ### Визуализация
# Так выглядит решение для динамической сетке
ftw = isTravis ? range(1, stop = M+1, length=15) : [1; 2:div(M+1, 80):M+1];
make_gif(u, XX, Tₘ, ϕl, ϕr, ϕ, f1_data, f2_data; name="solution_direct_ex3.gif", frames_to_write = ftw)

include("examples/example_direct_nonuniform_dparams.jl")

# ### Визуализация
# Так выглядит решение для стандартных данных динамической сетке.
ftw = [1; 2:div(M+1, 80):M+1];
make_gif(u, XX, Tₘ, ϕl, ϕr, ϕ, f1_data, f2_data; name="solution_direct_ex4.gif", frames_to_write = ftw)


text:
immutable OptimGARCH <: MathProgBase.SolverInterface.AbstractNLPEvaluator
    x::Array{Float64, 1}
    p::Int
    q::Int
    objval::Array{Float64,1}
    status::Array{Symbol, 1}
    solver::Array{MathProgBase.SolverInterface.AbstractMathProgSolver, 1}
end

OptimGARCH(p, q) = OptimGARCH(Array(Float64, 1), p, q, [0.0], [:Unsolved],
                              [FinMetricsDefaultSolver()])

immutable GARCH <: ContinuousUnivariateDistribution
    ω::Array{Float64, 1}
    α::Array{Float64, 1}
    β::Array{Float64, 1}
    x0::Array{Float64, 1}
    σ²₀::Array{Float64, 1}
    o::OptimGARCH
    dist::Function
    fitted::Array{Bool, 1}
    p::Int
    q::Int
end

function GARCH(p, q)
    ## Init is the vector
    ## init = [1 eps_{t-1} eps_{t-2} ... eps_{}]
    GARCH(Array(Float64, 1),
          Array(Float64, p),
          Array(Float64, q),
          zeros(p),
          zeros(q),
          OptimGARCH(p, q),
          s -> Normal(0,s),
          [false],
          p, q)
end

size(g::GARCH) = (g.p, g.q)

function update_parms!(g::GARCH, theta)
    ## Writes the parameters in theta into GARCH
    ## [ω; α; β]
    p, q = size(g)
    @assert length(theta) == q + p + 1 "length of theta inconsistent"
    copy!(g.ω, theta[1])
    copy!(g.α, theta[2:2+p-1])
    copy!(g.β, theta[2+p:end])
end

function getgarchparms(g)
    (g.p, g.q, g.σ²₀[1], g.ω[1], g.α, g.β)
end

function simulate(g::GARCH, n; d::Function = g.dist, burnin::Int = 0)
    (p, q, σ²₀, ω, α, β) = getgarchparms(g)
    maxpq = max(p, q)

    σ² = zeros(Float64, n + burnin)
    x  = Array(Float64, n + burnin)

    sigma2 = sum(α) + sum(β)

    @assert sigma2 <1 "GARCH does not have finite variance"

    sigma2 = ω/(1-sigma2)

    x[1:maxpq]  = rand(d(√sigma2), maxpq)
    σ²[1:maxpq] = sigma2

    @inbounds for j = maxpq+1:n + burnin
            for i = 1:q
                σ²[j] = σ²[j] + β[i]*σ²[j-i]
            end
            for i = 1:p
                σ²[j] = σ²[j] + α[i]*x[j-i]^2
            end
            σ²[j] += ω
            x[j] = Distributions.rand(d(√σ²[j]))
        end
        x[burnin+1:end]
end

function calculateVolatilityProcess(ϵ, omega, a, b)
    p = length(a)
    q = length(b)
    vare = var(ϵ)
    σ² = zeros(eltype(a), length(ϵ))
    @inbounds for j = 1:length(ϵ)
        for i = 1:q
            if j-i > 0
                σ²[j] = σ²[j] + b[i]*σ²[j - i]
            else
                σ²[j] = σ²[j] + b[i]*vare
            end
        end
        for i = 1:p
            if j - i > 0
                σ²[j] = σ²[j] + a[i]*ϵ[j - i]^2
            else
                σ²[j] = σ²[j] + a[i]*vare
            end
        end
        σ²[j] += omega[1]
    end
    σ²
end

function StatsBase.loglikelihood(g::GARCH, x, theta)
    n = length(x)
    p = g.p
    q = g.q
    omega = theta[1]
    a = theta[2:1+p]
    b = theta[p+2:end]
    σ² = calculateVolatilityProcess(x, omega, a, b)
    l = zero(eltype(theta))
    @simd for j = eachindex(x)
        @inbounds l += -x[j]^2/σ²[j] - log(σ²[j])
    end
    (l  - n*log2π)/2
end

function StatsBase.loglikelihood(g::OptimGARCH, theta)
    x = g.x
    p = g.p
    q = g.q
    n = length(x)
    omega = theta[1]
    a = theta[2:1+p]
    b = theta[p+2:end]
    σ² = calculateVolatilityProcess(x, omega, a, b)
    l = zero(eltype(theta))
    @simd for j = eachindex(x)
        @inbounds l += -x[j]^2/σ²[j] - log(σ²[j])
    end
    (l  - n*log2π)/2
end

function garch(y, theta; p=1, q=1, solver = FinMetricsDefaultSolver())
    @assert length(theta) == p + q + 1 "parameter size inconsistent with
    GARCH($p, $q)"
    g = GARCH(p, q)
    update_parms!(g, theta)
    mod = fit(g, y, theta, solver)
    # println(MathProgBase.status(mod))
    theta = MathProgBase.SolverInterface.getsolution(mod)
    update_parms!(g, theta)
    g.o.status[1] = MathProgBase.SolverInterface.status(mod)
    g.o.objval[1] = MathProgBase.SolverInterface.getobjval(mod)
    g.o.solver[1] = solver
    g.fitted[1] = g.o.status[1] == :Optimal ? true : false
    g
end

function garch(y; p=1, q=1, solver = FinMetricsDefaultSolver())
    theta = [var(y); fill(.3/p, p); fill(0.6/q, q)]
    g = GARCH(p, q)
    update_parms!(g, theta)
    mod = fit(g, y, theta, solver)
    # println(MathProgBase.status(mod))
    theta = MathProgBase.SolverInterface.getsolution(mod)
    update_parms!(g, theta)
    g.o.status[1] = MathProgBase.SolverInterface.status(mod)
    g.o.objval[1] = MathProgBase.SolverInterface.getobjval(mod)
    g.o.solver[1] = solver
    g.fitted[1] = g.o.status[1] == :Optimal ? true : false
    g
end

function MathProgBase.initialize(d::OptimGARCH, rf::Vector{Symbol})
    for feat in rf
        if !(feat in [:Grad, :Jac])
            error("Unsupported feature $feat")
        end
    end
end

MathProgBase.features_available(d::OptimGARCH) = [:Grad, :Jac]

function MathProgBase.eval_f(d::OptimGARCH, theta)
    loglikelihood(d, theta)
end

function MathProgBase.eval_grad_f(d::OptimGARCH, g, theta)
    function obj(par)
        loglikelihood(d, par)
    end
    ForwardDiff.gradient!(g, obj, theta, Chunk{min(length(theta), 10)}())
end

MathProgBase.jac_structure(d::OptimGARCH) =  Int[],Int[]
MathProgBase.eval_jac_g(d::OptimGARCH, J, x) =  nothing

MathProgBase.eval_g(d::OptimGARCH, x, y) = nothing

function StatsBase.fit(g::GARCH, x, theta, solver = IpoptSolver(print_level = 4))
    push!(g.o.x, x...)
    shift!(g.o.x)
    p = g.p
    q = g.q
    np = length(theta)
    lb = [1e-10;
          zeros(p);
          zeros(q)]
    ub = [+10;
          ones(p).*.999;
          ones(q).*.999]

    mod = MathProgBase.NonlinearModel(solver)
    MathProgBase.loadproblem!(mod, np, 0, lb, ub, Float64[], Float64[], :Max, g.o)
    MathProgBase.setwarmstart!(mod, theta)
    MathProgBase.optimize!(mod)
    mod
end

getgarchparms(g) = (g.p, g.q, g.σ²₀[1], g.ω[1], g.α, g.β)
setinitialvar(g, s0::Float64) = g.σ²₀[:] = s0

export garch, GARCH, setinitialvar, getgarchparms, OptimGARCH


text:
using Dagger: DArray, Thunk

include("dagger_utils.jl")

# Backend

function arrays(v)
  s = Set()
  DataFlow.prefor(v) do v
    vtype(v) isa ArrayT && push!(s, v)
  end
  return s
end

function split_loop(v::IVertex)
  v = notype(v)
  @assert v.value isa Loop
  is = v[3:end]
  ls = [vcall(length, i) for i in is]
  v.inputs[3:end] = [vcall(UnitRange, 1, l) for l in ls]
  notype(v[2]).inputs[2:end] = ls
  body = tolambda(v, is...)
  out = vcall(DArray{Any,length(is)}, is...)
  vertex(Loop(), body, out, is...)
end

# TODO: variables and arguments should probably be swapped
argtuple(v) =
  vertex(Lambda(1, spliceinputs(v.value.body,
                                [inputnode(i) for i = 1:length(v.inputs)]...,
                                [inputnode(length(v.inputs)+1, i) for i = 1:v.value.args]...)),
         v.inputs...)

function compile_loop(v)
  lambda = v[1]
  is = map(x -> x.value.value, v[3:end])
  inputd(i) = inputnode(length(v[1,:])+findfirst(is, i))
  lambda = applybody(lambda) do body
    vars = delete!(arrays(body), body[2])
    vcall(Thunk, tolambda(body, vars...),
          [vcall(chslice, var, inputd.(vtype(var).xs)...) for var in vars]...)
  end |> argtuple
  striptypes(vcall(DArray{Any,length(is)}, lambda, vcall(tuple, is...)))
end

function daggerv(f::Func, ts...)
  ar, v = infer(f, ts...)
  v = insert_domains(compile_loop(split_loop(v)), ar)
  v = tolambda(v, length(ts))
end

dagger(a...) = daggerv(a...) |> syntax |> eval

max_stars_repo_name: JuliaTagBot/Tokamak

max_issues_repo_name: JuliaTagBot/Tokamak

max_forks_repo_name: FluxML/Tokamak


text:
# Import functions that act on JuMP Models

export setbranchcallback,
       addbranchcallback,
       addbranch,
       nobranches,
       setincumbentcallback,
       addincumbentcallback,
       acceptincumbent,
       rejectincumbent,
       nobranches

type CPLEXcb
    branchcallback
    incumbentcallback
end

function initcb(m::JuMP.Model)
    if !haskey(m.ext, :cb)
        m.ext[:cb] = CPLEXcb(nothing,nothing)
    end
end

function solvehook(m::JuMP.Model; kwargs...)
    JuMP.build(m)
    if isa(m.ext[:cb].branchcallback, Function)
        function branchcallback(d::MathProgCallbackData)
            state = cbgetstate(d)
            if state == :MIPSol
                cbgetmipsolution(d,m.colVal)
            else
                cbgetlpsolution(d,m.colVal)
            end
            m.ext[:cb].branchcallback(d)
        end
        setbranchcallback!(m.internalModel, branchcallback)
    end
    if isa(m.ext[:cb].incumbentcallback, Function)
        function incumbentcallback(d::MathProgCallbackData)
            state = cbgetstate(d)
            @assert state == :MIPIncumbent
            m.colVal = copy(d.sol)
            m.ext[:cb].incumbentcallback(d)
        end
        setincumbentcallback!(m.internalModel, incumbentcallback)
    end
    JuMP.solve(m; ignore_solve_hook=true, kwargs...)
end

addbranchcallback(m::JuMP.Model, f::Function) = setbranchcallback(m, f)
function setbranchcallback(m::JuMP.Model, f::Function)
    initcb(m)
    m.ext[:cb].branchcallback = f
    JuMP.setsolvehook(m, solvehook)
    nothing
end

function addbranch(cbdata::MathProgCallbackData, aff::JuMP.LinearConstraint)
    addbranch(cbdata, aff, cbgetnodeobjval(cbdata))
end

function addbranch(cbdata::MathProgCallbackData, aff::JuMP.LinearConstraint, nodeest)
    if length(aff.terms.vars) == 1 # branch on variable
        @assert (isinf(aff.lb) + isinf(aff.ub) == 1)
        up = isinf(aff.ub)
        idx = aff.terms.vars[1].col
        bnd = (up ? aff.lb : aff.ub) / aff.terms.coeffs[1]
        #nodeest = 0.0
        if up
            cbaddboundbranchup!(  cbdata, idx, bnd, nodeest)
        else
            cbaddboundbranchdown!(cbdata, idx, bnd, nodeest)
        end
    else
        indices = [x.col for x in aff.terms.vars]
        coeffs  = [v for v in aff.terms.coeffs]
        lb, ub = aff.lb, aff.ub
        isinf(lb) || isinf(ub) || lb == ub || error("Cannot branch on ranged constraint $aff")
        if isinf(lb)
            sense = 'L'
            rhs = ub
        elseif isinf(ub)
            sense = 'G'
            rhs = lb
        else
            sense = 'E'
            rhs = lb
        end
        cbaddconstrbranch!(cbdata, indices, coeffs, rhs, sense, nodeest)
    end
    nothing
end

# This tells CPLEX that the current node should spawn zero branches
function nobranches(d::CplexBranchCallbackData)
    unsafe_store!(d.userinteraction_p, convert(Cint,CPX_CALLBACK_SET), 1)
    nothing
end

addincumbentcallback(m::JuMP.Model, f::Function) = setincumbentcallback(m, f)
function setincumbentcallback(m::JuMP.Model, f::Function)
    initcb(m)
    m.ext[:cb].incumbentcallback = f
    JuMP.setsolvehook(m, solvehook)
    nothing
end

acceptincumbent(cbdata::MathProgCallbackData) =
    cbprocessincumbent!(cbdata, true)

rejectincumbent(cbdata::MathProgCallbackData) =
    cbprocessincumbent!(cbdata, false)


text:
####
#### Network
####

"""
    Network

A graph along with strings labeling the vertices.
"""
struct Network
    graph::Graph
    persons::Vector{String}
end

"""
    Network()

Create a network with no persons.
"""
Network() = Network(Graph(), String[])

"""
    Network(persons)

Create a network initialized with the iterator `persons` of `String`s.
The network contains no friend relations.
"""
Network(persons) = Network(Graph(length(persons)), collect(persons))

## Make Network behave as a scalar in broadcasting expressions. That is, when
## automatically broadcasting a scalar function over arrays, make Network behave
## like a scalar would.
Base.Broadcast.broadcastable(net::Network) = Ref(net)

# Show a compact representation.
function Base.show(io::IO, net::Network)
    print(io, "Network(num_persons=$(nv(net.graph)), num_friendships=$(ne(net.graph)))")
    return nothing
end

# Forward some functions to the graph.
for func in (:adj_list, :add_vertex!)
    @eval ($func)(net::Network, args...) = ($func)(net.graph, args...)
end

"""
    persons(net::Network)

Return the list of all persons in `net`.
"""
persons(net::Network) = net.persons

"""
    person(net::Network, i::Integer) = (net.persons)[i]

Return the name (`String`) of the `i`th person in `net`.
"""
person(net::Network, i::Integer) = (net.persons)[i]

## Index notation looks up a person's index from the name. Eg.
## net["Alice"] -> 10
Base.getindex(net::Network, person::AbstractString) = findfirst(isequal(person), net.persons)

"""
    ispresent(net::Network, person)

Return `true` if `person` is in `net`.
"""
ispresent(net::Network, person) = (findfirst(isequal(person), net.persons) != nothing)

"""
    friends(net::Network, person)

Return the list of friends of `person`.
"""
function friends(net::Network, person)
    iperson = net[person]
    friend_inds::Vector{Int} = adj_list(net)[iperson]
    return net.persons[friend_inds]
end

"""
    add_person!(net::Network, person::AbstractString)

Add `person` to `net`. No friend relations are added.
"""
function add_person!(net::Network, person::AbstractString)
    persons = net.persons
    ispresent(net, person) && error("Person $person already present.")
    add_vertex!(net)
    push!(persons, person)
    return net
end

"""
    friend_pair!(net::Network, person1, person2)

Cause `person1` to "friend" `person2` (and vice-versa) in the network `net`.
"""
function friend_pair!(net::Network, person1, person2)
    add_edge!(net.graph, net[person1], net[person2])
    return net
end

"""
    defriend_pair!(net::Network, person1, person2)

Cause `person1` to "defriend" `person2` in the network `net`.
This just removes the symmetric friend relation between the
two persons.
"""
function defriend_pair!(net::Network, person1, person2)
    del_edge!(net.graph, net[person1], net[person2])
    return net
end

"""
    degree_of_separation(net::Network, person1, person2)

Return the degree of separation between `person1` and `person2`.
If the persons are equal, the distance is zero. If they are nearest
neighbors, it is one. In general, it is the length of a shortest
friendship path between the persons.
"""
function degree_of_separation(net::Network, person1, person2)
    return shortest_path_length(net.graph, net[person1], net[person2])
end


text:
function add_to_lst(lst, elmt)
    if length(lst) > 0
        insert_idx = -1
        to_remove_idx = []
        if elmt[1] <= lst[1][1] && elmt[2] < lst[1][2]
            # avant le premier
            insert_idx = 1
            push!(to_remove_idx, 1)
        end
        if elmt[1] > lst[length(lst)][1] && elmt[2] < lst[length(lst)][2]
            # après le dernier
            push!(lst, elmt)
        else
            for i = 2:length(lst)
                if insert_idx != -1 && elmt[2] <= lst[i][2]
                    # elmt va être inséré avant, donc on supprime tout élément avec z2 supérieur
                    push!(to_remove_idx, i)
                elseif insert_idx != -1
                    # les éléments suivant on z1 plus grand mais z2 plus petit on peut s'arrêter
                    break
                elseif lst[i][1] < elmt[1] && lst[i][2] < elmt[2]
                    # dominé par un point de la liste, on s'arrête
                    return
                elseif lst[i][1] > elmt[1]
                    insert_idx = i
                    if elmt[2] <= lst[i][2]
                        push!(to_remove_idx, i)
                    end
                elseif lst[i][1] == elmt[1]
                    if elmt[2] < lst[i][2]
                        insert_idx = i
                        push!(to_remove_idx, i)
                    else
                        return
                    end
                end
            end
            if insert_idx != -1
                insert!(lst, insert_idx, elmt)
            end
            for idx_remove in reverse(to_remove_idx)
                if idx_remove >= insert_idx && insert_idx != -1
                    popat!(lst, idx_remove + 1)
                else
                    popat!(lst, idx_remove)
                end
            end
        end
    else
        push!(lst, elmt)
    end
end