text:
#  Copyright 2017, Iain Dunning, Joey Huchette, Miles Lubin, and contributors
#  This Source Code Form is subject to the terms of the Mozilla Public
#  License, v. 2.0. If a copy of the MPL was not distributed with this
#  file, You can obtain one at https://mozilla.org/MPL/2.0/.

# The tests here check JuMP's model generation and communication with solvers.
# Model generation is checked by comparing the internal model with a serialized
# test model (in MOIU's lightweight text format).
# Communication with solvers is tested by using a mock solver with solution data
# that we feed to it. Prior to using this testing approach, we would test JuMP
# by calling real solvers, which was flakey and slow.

# Note: No attempt is made to use correct solution data. We're only testing
# that the plumbing works. This could change if JuMP gains the ability to verify
# feasibility independently of a solver.

using LinearAlgebra, Test
using JuMP

@testset "Generation and solve with fake solver" begin
    @testset "LP" begin
        m = Model()
        @variable(m, x <= 2.0)
        @variable(m, y >= 0.0)
        @objective(m, Min, -x)

        c = @constraint(m, x + y <= 1)

        JuMP.set_name(JuMP.UpperBoundRef(x), "xub")
        JuMP.set_name(JuMP.LowerBoundRef(y), "ylb")
        JuMP.set_name(c, "c")

        modelstring = """
        variables: x, y
        minobjective: -1.0*x
        xub: x <= 2.0
        ylb: y >= 0.0
        c: x + y <= 1.0
        """

        model = MOIU.Model{Float64}()
        MOIU.loadfromstring!(model, modelstring)
        MOIU.test_models_equal(
            JuMP.backend(m).model_cache,
            model,
            ["x", "y"],
            ["c", "xub", "ylb"],
        )

        set_optimizer(
            m,
            () -> MOIU.MockOptimizer(
                MOIU.Model{Float64}(),
                eval_objective_value = false,
            ),
        )
        JuMP.optimize!(m)

        mockoptimizer = JuMP.backend(m).optimizer.model
        MOI.set(mockoptimizer, MOI.TerminationStatus(), MOI.OPTIMAL)
        MOI.set(mockoptimizer, MOI.RawStatusString(), "solver specific string")
        MOI.set(mockoptimizer, MOI.ObjectiveValue(), -1.0)
        MOI.set(mockoptimizer, MOI.ResultCount(), 1)
        MOI.set(mockoptimizer, MOI.PrimalStatus(), MOI.FEASIBLE_POINT)
        MOI.set(mockoptimizer, MOI.DualStatus(), MOI.FEASIBLE_POINT)
        MOI.set(
            mockoptimizer,
            MOI.VariablePrimal(),
            JuMP.optimizer_index(x),
            1.0,
        )
        MOI.set(
            mockoptimizer,
            MOI.VariablePrimal(),
            JuMP.optimizer_index(y),
            0.0,
        )
        MOI.set(
            mockoptimizer,
            MOI.ConstraintDual(),
            JuMP.optimizer_index(c),
            -1.0,
        )
        MOI.set(
            mockoptimizer,
            MOI.ConstraintDual(),
            JuMP.optimizer_index(JuMP.UpperBoundRef(x)),
            0.0,
        )
        MOI.set(
            mockoptimizer,
            MOI.ConstraintDual(),
            JuMP.optimizer_index(JuMP.LowerBoundRef(y)),
            1.0,
        )
        MOI.set(mockoptimizer, MOI.SimplexIterations(), 1)
        MOI.set(mockoptimizer, MOI.BarrierIterations(), 1)
        MOI.set(mockoptimizer, MOI.NodeCount(), 1)

        #@test JuMP.isattached(m)
        @test JuMP.has_values(m)

        @test MOI.OPTIMAL == @inferred JuMP.termination_status(m)
        @test "solver specific string" == JuMP.raw_status(m)
        @test MOI.FEASIBLE_POINT == @inferred JuMP.primal_status(m)

        @test 1.0 == @inferred JuMP.value(x)
        @test 0.0 == @inferred JuMP.value(y)
        @test 1.0 == @inferred JuMP.value(x + y)
        @test 1.0 == @inferred JuMP.value(c)
        @test -1.0 == @inferred JuMP.objective_value(m)
        @test -1.0 == @inferred JuMP.dual_objective_value(m)

        @test MOI.FEASIBLE_POINT == @inferred JuMP.dual_status(m)
        @test -1.0 == @inferred JuMP.dual(c)
        @test 0.0 == @inferred JuMP.dual(JuMP.UpperBoundRef(x))
        @test 1.0 == @inferred JuMP.dual(JuMP.LowerBoundRef(y))
        @test 1 == JuMP.simplex_iterations(m)
        @test 1 == JuMP.barrier_iterations(m)
        @test 1 == JuMP.node_count(m)
    end

    @testset "LP (Direct mode)" begin
        mockoptimizer = MOIU.MockOptimizer(
            MOIU.Model{Float64}(),
            eval_objective_value = false,
        )

        m = JuMP.direct_model(mockoptimizer)
        @variable(m, x <= 2.0)
        @variable(m, y >= 0.0)
        @objective(m, Min, -x)

        c = @constraint(m, x + y <= 1)
        MOI.set(mockoptimizer, MOI.TerminationStatus(), MOI.OPTIMAL)
        MOI.set(mockoptimizer, MOI.RawStatusString(), "solver specific string")
        MOI.set(mockoptimizer, MOI.ObjectiveValue(), -1.0)
        MOI.set(mockoptimizer, MOI.ResultCount(), 1)
        MOI.set(mockoptimizer, MOI.PrimalStatus(), MOI.FEASIBLE_POINT)
        MOI.set(mockoptimizer, MOI.DualStatus(), MOI.FEASIBLE_POINT)
        MOI.set(
            mockoptimizer,
            MOI.VariablePrimal(),
            JuMP.optimizer_index(x),
            1.0,
        )
        MOI.set(
            mockoptimizer,
            MOI.VariablePrimal(),
            JuMP.optimizer_index(y),
            0.0,
        )
        MOI.set(
            mockoptimizer,
            MOI.ConstraintDual(),
            JuMP.optimizer_index(c),
            -1.0,
        )
        MOI.set(
            mockoptimizer,
            MOI.ConstraintDual(),
            JuMP.optimizer_index(JuMP.UpperBoundRef(x)),
            0.0,
        )
        MOI.set(
            mockoptimizer,
            MOI.ConstraintDual(),
            JuMP.optimizer_index(JuMP.LowerBoundRef(y)),
            1.0,
        )
        MOI.set(mockoptimizer, MOI.SimplexIterations(), 1)
        MOI.set(mockoptimizer, MOI.BarrierIterations(), 1)
        MOI.set(mockoptimizer, MOI.NodeCount(), 1)

        JuMP.optimize!(m)

        #@test JuMP.isattached(m)
        @test JuMP.has_values(m)

        @test MOI.OPTIMAL == @inferred JuMP.termination_status(m)
        @test "solver specific string" == JuMP.raw_status(m)
        @test MOI.FEASIBLE_POINT == @inferred JuMP.primal_status(m)

        @test 1.0 == @inferred JuMP.value(x)
        @test 0.0 == @inferred JuMP.value(y)
        @test 1.0 == @inferred JuMP.value(x + y)
        @test -1.0 == @inferred JuMP.objective_value(m)

        @test MOI.FEASIBLE_POINT == @inferred JuMP.dual_status(m)
        @test -1.0 == @inferred JuMP.dual(c)
        @test 0.0 == @inferred JuMP.dual(JuMP.UpperBoundRef(x))
        @test 1.0 == @inferred JuMP.dual(JuMP.LowerBoundRef(y))
        @test 1 == JuMP.simplex_iterations(m)
        @test 1 == JuMP.barrier_iterations(m)
        @test 1 == JuMP.node_count(m)
    end

    # TODO: test Manual mode

    @testset "IP" begin
        # Tests the solver= keyword.
        m = Model(
            () -> MOIU.MockOptimizer(
                MOIU.Model{Float64}(),
                eval_objective_value = false,
            ),
            caching_mode = MOIU.AUTOMATIC,
        )
        @variable(m, x == 1.0, Int)
        @variable(m, y, Bin)
        @objective(m, Max, x)

        JuMP.set_name(JuMP.FixRef(x), "xfix")
        JuMP.set_name(JuMP.IntegerRef(x), "xint")
        JuMP.set_name(JuMP.BinaryRef(y), "ybin")

        modelstring = """
        variables: x, y
        maxobjective: x
        xfix: x == 1.0
        xint: x in Integer()
        ybin: y in ZeroOne()
        """

        model = MOIU.Model{Float64}()
        MOIU.loadfromstring!(model, modelstring)
        MOIU.test_models_equal(
            JuMP.backend(m).model_cache,
            model,
            ["x", "y"],
            ["xfix", "xint", "ybin"],
        )

        MOIU.attach_optimizer(m)

        mockoptimizer = JuMP.backend(m).optimizer.model
        MOI.set(mockoptimizer, MOI.TerminationStatus(), MOI.OPTIMAL)
        MOI.set(mockoptimizer, MOI.RawStatusString(), "solver specific string")
        MOI.set(mockoptimizer, MOI.ObjectiveValue(), 1.0)
        MOI.set(mockoptimizer, MOI.ResultCount(), 1)
        MOI.set(mockoptimizer, MOI.PrimalStatus(), MOI.FEASIBLE_POINT)
        MOI.set(
            mockoptimizer,
            MOI.VariablePrimal(),
            JuMP.optimizer_index(x),
            1.0,
        )
        MOI.set(
            mockoptimizer,
            MOI.VariablePrimal(),
            JuMP.optimizer_index(y),
            0.0,
        )
        MOI.set(mockoptimizer, MOI.DualStatus(), MOI.NO_SOLUTION)
        MOI.set(mockoptimizer, MOI.SimplexIterations(), 1)
        MOI.set(mockoptimizer, MOI.BarrierIterations(), 1)
        MOI.set(mockoptimizer, MOI.NodeCount(), 1)
        MOI.set(mockoptimizer, MOI.RelativeGap(), 0.0)

        JuMP.optimize!(m)

        #@test JuMP.isattached(m)
        @test JuMP.has_values(m)

        @test MOI.OPTIMAL == @inferred JuMP.termination_status(m)
        @test "solver specific string" == JuMP.raw_status(m)
        @test MOI.FEASIBLE_POINT == @inferred JuMP.primal_status(m)

        @test 1.0 == @inferred JuMP.value(x)
        @test 0.0 == @inferred JuMP.value(y)
        @test 1.0 == @inferred JuMP.objective_value(m)

        @test 1 == JuMP.simplex_iterations(m)
        @test 1 == JuMP.barrier_iterations(m)
        @test 1 == JuMP.node_count(m)
        @test 0.0 == @inferred JuMP.relative_gap(m)

        @test !JuMP.has_duals(m)
    end

    @testset "QCQP" begin
        m = Model()
        @variable(m, x)
        @variable(m, y)
        @objective(m, Min, x^2)

        @constraint(m, c1, 2x * y <= 1)
        @constraint(m, c2, y^2 == x^2)
        @constraint(m, c3, 2x + 3y * x >= 2)

        modelstring = """
        variables: x, y
        minobjective: 1*x*x
        c1: 2*x*y <= 1.0
        c2: 1*y*y + -1*x*x == 0.0
        c3: 2x + 3*y*x >= 2.0
        """

        model = MOIU.Model{Float64}()
        MOIU.loadfromstring!(model, modelstring)
        MOIU.test_models_equal(
            JuMP.backend(m).model_cache,
            model,
            ["x", "y"],
            ["c1", "c2", "c3"],
        )

        set_optimizer(
            m,
            () -> MOIU.MockOptimizer(
                MOIU.Model{Float64}(),
                eval_objective_value = false,
            ),
        )
        JuMP.optimize!(m)

        mockoptimizer = JuMP.backend(m).optimizer.model
        MOI.set(mockoptimizer, MOI.TerminationStatus(), MOI.OPTIMAL)
        MOI.set(mockoptimizer, MOI.RawStatusString(), "solver specific string")
        MOI.set(mockoptimizer, MOI.ObjectiveValue(), -1.0)
        MOI.set(mockoptimizer, MOI.ResultCount(), 1)
        MOI.set(mockoptimizer, MOI.PrimalStatus(), MOI.FEASIBLE_POINT)
        MOI.set(mockoptimizer, MOI.DualStatus(), MOI.FEASIBLE_POINT)
        MOI.set(
            mockoptimizer,
            MOI.VariablePrimal(),
            JuMP.optimizer_index(x),
            1.0,
        )
        MOI.set(
            mockoptimizer,
            MOI.VariablePrimal(),
            JuMP.optimizer_index(y),
            0.0,
        )
        MOI.set(
            mockoptimizer,
            MOI.ConstraintDual(),
            JuMP.optimizer_index(c1),
            -1.0,
        )
        MOI.set(
            mockoptimizer,
            MOI.ConstraintDual(),
            JuMP.optimizer_index(c2),
            2.0,
        )
        MOI.set(
            mockoptimizer,
            MOI.ConstraintDual(),
            JuMP.optimizer_index(c3),
            3.0,
        )
        MOI.set(mockoptimizer, MOI.SimplexIterations(), 1)
        MOI.set(mockoptimizer, MOI.BarrierIterations(), 1)
        MOI.set(mockoptimizer, MOI.NodeCount(), 1)

        #@test JuMP.isattached(m)
        @test JuMP.has_values(m)

        @test MOI.OPTIMAL == @inferred JuMP.termination_status(m)
        @test "solver specific string" == JuMP.raw_status(m)
        @test MOI.FEASIBLE_POINT == @inferred JuMP.primal_status(m)

        @test 1.0 == @inferred JuMP.value(x)
        @test 0.0 == @inferred JuMP.value(y)
        @test -1.0 == @inferred JuMP.objective_value(m)
        @test 5.0 == @inferred JuMP.dual_objective_value(m)

        @test MOI.FEASIBLE_POINT == @inferred JuMP.dual_status(m)
        @test -1.0 == @inferred JuMP.dual(c1)
        @test 2.0 == @inferred JuMP.dual(c2)
        @test 3.0 == @inferred JuMP.dual(c3)

        @test 2.0 == @inferred JuMP.value(2 * x + 3 * y * x)
        @test 1 == JuMP.simplex_iterations(m)
        @test 1 == JuMP.barrier_iterations(m)
        @test 1 == JuMP.node_count(m)
    end

    @testset "SOC" begin
        m = Model()
        @variables m begin
            x
            y
            z
        end
        @objective(m, Max, 1.0 * x)
        @constraint(m, varsoc, [x, y, z] in SecondOrderCone())
        # Equivalent to `[x+y,z,1.0] in SecondOrderCone()`
        @constraint(m, affsoc, [x + y, z, 1.0] in MOI.SecondOrderCone(3))
        @constraint(m, rotsoc, [x + 1, y, z] in RotatedSecondOrderCone())

        modelstring = """
        variables: x, y, z
        maxobjective: 1.0*x
        varsoc: [x,y,z] in SecondOrderCone(3)
        affsoc: [x+y,z,1.0] in SecondOrderCone(3)
        rotsoc: [x+1,y,z] in RotatedSecondOrderCone(3)
        """

        model = MOIU.Model{Float64}()
        MOIU.loadfromstring!(model, modelstring)
        MOIU.test_models_equal(
            JuMP.backend(m).model_cache,
            model,
            ["x", "y", "z"],
            ["varsoc", "affsoc", "rotsoc"],
        )

        mockoptimizer = MOIU.MockOptimizer(
            MOIU.Model{Float64}(),
            eval_objective_value = false,
            eval_variable_constraint_dual = false,
        )
        MOIU.reset_optimizer(m, mockoptimizer)
        MOIU.attach_optimizer(m)

        MOI.set(mockoptimizer, MOI.TerminationStatus(), MOI.OPTIMAL)
        MOI.set(mockoptimizer, MOI.RawStatusString(), "solver specific string")
        MOI.set(mockoptimizer, MOI.ResultCount(), 1)
        MOI.set(mockoptimizer, MOI.PrimalStatus(), MOI.FEASIBLE_POINT)
        MOI.set(mockoptimizer, MOI.DualStatus(), MOI.FEASIBLE_POINT)
        MOI.set(
            mockoptimizer,
            MOI.VariablePrimal(),
            JuMP.optimizer_index(x),
            1.0,
        )
        MOI.set(
            mockoptimizer,
            MOI.VariablePrimal(),
            JuMP.optimizer_index(y),
            0.0,
        )
        MOI.set(
            mockoptimizer,
            MOI.VariablePrimal(),
            JuMP.optimizer_index(z),
            0.0,
        )
        MOI.set(
            mockoptimizer,
            MOI.ConstraintDual(),
            JuMP.optimizer_index(varsoc),
            [-1.0, -2.0, -3.0],
        )
        MOI.set(
            mockoptimizer,
            MOI.ConstraintDual(),
            JuMP.optimizer_index(affsoc),
            [1.0, 2.0, 3.0],
        )
        MOI.set(mockoptimizer, MOI.SimplexIterations(), 1)
        MOI.set(mockoptimizer, MOI.BarrierIterations(), 1)
        MOI.set(mockoptimizer, MOI.NodeCount(), 1)

        JuMP.optimize!(m)

        #@test JuMP.isattached(m)
        @test JuMP.has_values(m)

        @test MOI.OPTIMAL == @inferred JuMP.termination_status(m)
        @test "solver specific string" == JuMP.raw_status(m)
        @test MOI.FEASIBLE_POINT == @inferred JuMP.primal_status(m)

        @test 1.0 == @inferred JuMP.value(x)
        @test 0.0 == @inferred JuMP.value(y)
        @test 0.0 == @inferred JuMP.value(z)

        @test JuMP.has_duals(m)
        @test [-1.0, -2.0, -3.0] == @inferred JuMP.dual(varsoc)
        @test [1.0, 2.0, 3.0] == @inferred JuMP.dual(affsoc)
        @test 1 == JuMP.simplex_iterations(m)
        @test 1 == JuMP.barrier_iterations(m)
        @test 1 == JuMP.node_count(m)
    end

    @testset "SDP" begin
        m = Model()
        @variable(m, x[1:2, 1:2], Symmetric)
        set_name(x[1, 1], "x11")
        set_name(x[1, 2], "x12")
        set_name(x[2, 2], "x22")
        @objective(m, Max, tr(x))
        var_psd = @constraint(m, x in PSDCone())
        set_name(var_psd, "var_psd")
        sym_psd = @constraint(m, Symmetric(x - [1.0 0.0; 0.0 1.0]) in PSDCone())
        set_name(sym_psd, "sym_psd")
        con_psd = @SDconstraint(m, x ⪰ [1.0 0.0; 0.0 1.0])
        set_name(con_psd, "con_psd")

        modelstring = """
        variables: x11, x12, x22
        maxobjective: 1.0*x11 + 1.0*x22
        var_psd: [x11,x12,x22] in PositiveSemidefiniteConeTriangle(2)
        sym_psd: [x11 + -1.0,x12,x22 + -1.0] in PositiveSemidefiniteConeTriangle(2)
        con_psd: [x11 + -1.0,x12,x12,x22 + -1.0] in PositiveSemidefiniteConeSquare(2)
        """

        model = MOIU.Model{Float64}()
        MOIU.loadfromstring!(model, modelstring)
        MOIU.test_models_equal(
            JuMP.backend(m).model_cache,
            model,
            ["x11", "x12", "x22"],
            ["var_psd", "sym_psd", "con_psd"],
        )

        mockoptimizer = MOIU.MockOptimizer(
            MOIU.Model{Float64}(),
            eval_objective_value = false,
            eval_variable_constraint_dual = false,
        )
        MOIU.reset_optimizer(m, mockoptimizer)
        MOIU.attach_optimizer(m)

        MOI.set(mockoptimizer, MOI.TerminationStatus(), MOI.OPTIMAL)
        MOI.set(mockoptimizer, MOI.RawStatusString(), "solver specific string")
        MOI.set(mockoptimizer, MOI.ResultCount(), 1)
        MOI.set(mockoptimizer, MOI.PrimalStatus(), MOI.FEASIBLE_POINT)
        MOI.set(mockoptimizer, MOI.DualStatus(), MOI.FEASIBLE_POINT)
        MOI.set(
            mockoptimizer,
            MOI.VariablePrimal(),
            JuMP.optimizer_index(x[1, 1]),
            1.0,
        )
        MOI.set(
            mockoptimizer,
            MOI.VariablePrimal(),
            JuMP.optimizer_index(x[1, 2]),
            2.0,
        )
        MOI.set(
            mockoptimizer,
            MOI.VariablePrimal(),
            JuMP.optimizer_index(x[2, 2]),
            4.0,
        )
        MOI.set(
            mockoptimizer,
            MOI.ConstraintDual(),
            JuMP.optimizer_index(var_psd),
            [1.0, 2.0, 3.0],
        )
        MOI.set(
            mockoptimizer,
            MOI.ConstraintDual(),
            JuMP.optimizer_index(sym_psd),
            [4.0, 5.0, 6.0],
        )
        MOI.set(
            mockoptimizer,
            MOI.ConstraintDual(),
            JuMP.optimizer_index(con_psd),
            [7.0, 8.0, 9.0, 10.0],
        )
        MOI.set(mockoptimizer, MOI.SimplexIterations(), 1)
        MOI.set(mockoptimizer, MOI.BarrierIterations(), 1)
        MOI.set(mockoptimizer, MOI.NodeCount(), 1)

        JuMP.optimize!(m)

        @test MOI.OPTIMAL == @inferred JuMP.termination_status(m)
        @test "solver specific string" == JuMP.raw_status(m)
        @test MOI.FEASIBLE_POINT == @inferred JuMP.primal_status(m)

        @test JuMP.has_values(m)
        @test [1.0 2.0; 2.0 4.0] == JuMP.value.(x)
        @test JuMP.value(var_psd) isa Symmetric
        @test [1.0 2.0; 2.0 4.0] == @inferred JuMP.value(var_psd)
        @test JuMP.value(sym_psd) isa Symmetric
        @test [0.0 2.0; 2.0 3.0] == @inferred JuMP.value(sym_psd)
        @test JuMP.value(con_psd) isa Matrix
        @test [0.0 2.0; 2.0 3.0] == @inferred JuMP.value(con_psd)

        @test JuMP.has_duals(m)
        @test JuMP.dual(var_psd) isa Symmetric
        @test [1.0 2.0; 2.0 3.0] == @inferred JuMP.dual(var_psd)
        @test JuMP.dual(sym_psd) isa Symmetric
        @test [4.0 5.0; 5.0 6.0] == @inferred JuMP.dual(sym_psd)
        @test JuMP.dual(con_psd) isa Matrix
        @test [7.0 9.0; 8.0 10.0] == @inferred JuMP.dual(con_psd)
        @test 1 == JuMP.simplex_iterations(m)
        @test 1 == JuMP.barrier_iterations(m)
        @test 1 == JuMP.node_count(m)
    end

    @testset "Solver doesn't support nonlinear constraints" begin
        model = Model(() -> MOIU.MockOptimizer(MOIU.Model{Float64}()))
        @variable(model, x)
        @NLobjective(model, Min, sin(x))
        err = ErrorException(
            "The solver does not support nonlinear problems " *
            "(i.e., NLobjective and NLconstraint).",
        )
        @test_throws err JuMP.optimize!(model)
    end

    @testset "ResultCount" begin
        m = Model()
        @variable(m, x >= 0.0)
        @variable(m, y >= 0.0)
        @objective(m, Max, x + y)
        @constraint(m, c1, x <= 2)
        @constraint(m, c2, x + y <= 1)

        model = MOIU.Model{Float64}()
        MOIU.loadfromstring!(
            model,
            """
variables: x, y
maxobjective: x + y
xub: x >= 0.0
ylb: y >= 0.0
c1: x <= 2.0
c2: x + y <= 1.0
""",
        )
        set_optimizer(
            m,
            () -> MOIU.MockOptimizer(
                MOIU.Model{Float64}(),
                eval_objective_value = false,
            ),
        )
        JuMP.optimize!(m)

        mock = JuMP.backend(m).optimizer.model
        MOI.set(mock, MOI.TerminationStatus(), MOI.OPTIMAL)
        MOI.set(mock, MOI.ResultCount(), 2)

        aff_expr = @expression(m, x + y)
        quad_expr = @expression(m, x * y)
        nl_expr = @NLexpression(m, log(x + y))

        @test JuMP.result_count(m) == 2

        MOI.set(mock, MOI.PrimalStatus(1), MOI.FEASIBLE_POINT)
        MOI.set(mock, MOI.DualStatus(1), MOI.FEASIBLE_POINT)
        MOI.set(mock, MOI.ObjectiveValue(1), 1.0)
        MOI.set(mock, MOI.DualObjectiveValue(1), 1.0)
        MOI.set(mock, MOI.VariablePrimal(1), JuMP.optimizer_index(x), 1.0)
        MOI.set(mock, MOI.VariablePrimal(1), JuMP.optimizer_index(y), 0.0)
        MOI.set(mock, MOI.ConstraintDual(1), JuMP.optimizer_index(c1), 0.0)
        MOI.set(mock, MOI.ConstraintDual(1), JuMP.optimizer_index(c2), -1.0)

        @test MOI.OPTIMAL == @inferred JuMP.termination_status(m)
        @test MOI.FEASIBLE_POINT == @inferred JuMP.primal_status(m, result = 1)
        @test MOI.FEASIBLE_POINT == @inferred JuMP.dual_status(m, result = 1)
        @test 1.0 == @inferred JuMP.objective_value(m, result = 1)
        @test 1.0 == @inferred JuMP.dual_objective_value(m, result = 1)
        @test 1.0 == @inferred JuMP.value(x, result = 1)
        @test 0.0 == @inferred JuMP.value(y, result = 1)
        @test 1.0 == @inferred JuMP.value(aff_expr, result = 1)
        @test 0.0 == @inferred JuMP.value(quad_expr, result = 1)
        @test 0.0 == @inferred JuMP.value(nl_expr, result = 1)
        @test 1.0 == @inferred JuMP.value(c2, result = 1)
        @test 0.0 == @inferred JuMP.dual(c1, result = 1)
        @test -1.0 == @inferred JuMP.dual(c2, result = 1)
        @test 0.0 == @inferred JuMP.dual(JuMP.LowerBoundRef(x), result = 1)
        @test 0.0 == @inferred JuMP.dual(JuMP.LowerBoundRef(y), result = 1)

        MOI.set(mock, MOI.PrimalStatus(2), MOI.FEASIBLE_POINT)
        MOI.set(mock, MOI.DualStatus(2), MOI.FEASIBLE_POINT)
        MOI.set(mock, MOI.ObjectiveValue(2), 1.0)
        MOI.set(mock, MOI.DualObjectiveValue(2), 1.0)
        MOI.set(mock, MOI.VariablePrimal(2), JuMP.optimizer_index(x), 0.0)
        MOI.set(mock, MOI.VariablePrimal(2), JuMP.optimizer_index(y), 1.0)
        MOI.set(mock, MOI.ConstraintDual(2), JuMP.optimizer_index(c1), 0.0)
        MOI.set(mock, MOI.ConstraintDual(2), JuMP.optimizer_index(c2), -1.0)

        @test MOI.FEASIBLE_POINT == @inferred JuMP.primal_status(m, result = 2)
        @test MOI.FEASIBLE_POINT == @inferred JuMP.dual_status(m, result = 2)
        @test 1.0 == @inferred JuMP.objective_value(m, result = 2)
        @test 1.0 == @inferred JuMP.dual_objective_value(m, result = 2)
        @test 0.0 == @inferred JuMP.value(x, result = 2)
        @test 1.0 == @inferred JuMP.value(y, result = 2)
        @test 1.0 == @inferred JuMP.value(aff_expr, result = 2)
        @test 0.0 == @inferred JuMP.value(quad_expr, result = 2)
        @test 0.0 == @inferred JuMP.value(nl_expr, result = 2)
        @test 1.0 == @inferred JuMP.value(c2, result = 2)
        @test 0.0 == @inferred JuMP.dual(c1, result = 2)
        @test -1.0 == @inferred JuMP.dual(c2, result = 2)
        @test 0.0 == @inferred JuMP.dual(JuMP.LowerBoundRef(x), result = 2)
        @test 0.0 == @inferred JuMP.dual(JuMP.LowerBoundRef(y), result = 2)

        @test MOI.NO_SOLUTION == @inferred JuMP.primal_status(m, result = 3)
        @test MOI.NO_SOLUTION == @inferred JuMP.dual_status(m, result = 3)
        @test_throws MOI.ResultIndexBoundsError JuMP.objective_value(
            m,
            result = 3,
        )
        @test_throws MOI.ResultIndexBoundsError JuMP.dual_objective_value(
            m,
            result = 3,
        )
        @test_throws MOI.ResultIndexBoundsError JuMP.value(x, result = 3)
        @test_throws MOI.ResultIndexBoundsError JuMP.value(aff_expr, result = 3)
        @test_throws MOI.ResultIndexBoundsError JuMP.value(
            quad_expr,
            result = 3,
        )
        @test_throws MOI.ResultIndexBoundsError JuMP.value(nl_expr, result = 3)
        @test_throws MOI.ResultIndexBoundsError JuMP.value(c2, result = 3)
        @test_throws MOI.ResultIndexBoundsError JuMP.dual(c1, result = 3)
        @test_throws MOI.ResultIndexBoundsError JuMP.dual(c2, result = 3)
        @test_throws MOI.ResultIndexBoundsError JuMP.dual(
            JuMP.LowerBoundRef(x),
            result = 3,
        )
        @test_throws MOI.ResultIndexBoundsError JuMP.dual(
            JuMP.LowerBoundRef(y),
            result = 3,
        )
    end
end

max_stars_repo_name: ethansaxenian/RosettaDecode

max_issues_repo_name: ethansaxenian/RosettaDecode

max_forks_repo_name: ethansaxenian/RosettaDecode


text:
export guided_path_finder

function _edge_generator(G::ImplicitGraph{T}, v::T, depth::Int = 1) where {T}
    @assert depth > 0 "Depth must be positive, argument was $depth"

    if depth == 1
        return [(v, w) for w in G[v]]
    end

    edges = _edge_generator(G, v, depth - 1)
    result = Tuple{T,T}[]

    visited = Set(first.(edges)) ∪ Set(last.(edges))
    for (x, y) in edges
        push!(result, (x, y))   # keep this edge
        for z in G[y]
            if z ∉ visited
                push!(result, (y, z))
            end
        end
    end
    return unique(result)
end

"""
    guided_path_finder(G, s, t; score, depth)

Find a path from vertex `s` to vertex `t` in an `ImplicitGraph` `G`.

* `score` is a function mapping vertices to `Int` values. It should decrease
   as vertices get closer to `t`. Ideally, `score(t)` should be the smallest
   possible value.

* `depth` controls the amount of look ahead as we explore each vertex.
  The default value is `1`.

* `verbose` controls how often status information is printed. Use `0` for
  no information.
"""
function guided_path_finder(
    G::ImplicitGraph{T},
    s::T,
    t::T;
    score::Function = x -> 1,
    depth::Int = 1,
    verbose::Int = 0,
)::Vector{T} where {T}

    PQ = PriorityQueue{T,Int}()
    PQ[s] = score(s)

    visited = Set{T}()               # Visited  positions
    trace_back = Dict{T,T}()         # Reverse edges
    trace_back[s] = s

    if s == t
        return [t]
    end

    best_vtx = s
    best_score = score(s)

    count = 0

    while length(PQ) > 0
        count += 1
        v = dequeue!(PQ)

        if score(v) < best_score
            best_score = score(v)
            best_vtx = v
        end

        if verbose > 0 && count % verbose == 0
            println("Iteration = $count")
            println("Queue size = $(length(PQ))")
            println("Current state")
            println(v)
            println(
                "Score = $(score(v))\t trying for $(score(t))\t with best so far $best_score\n\n",
            )
        end

        if v == t
            break
        end

        push!(visited, v)

        edges = _edge_generator(G, v, depth)

        for (x, y) in edges
            if y ∉ keys(trace_back)
                trace_back[y] = x
                PQ[y] = score(y)
            end
        end
    end

    rev_path = T[]
    push!(rev_path, t)

    while true
        x = rev_path[end]
        if x == s
            break
        end
        push!(rev_path, trace_back[x])
    end

    if verbose > 0
        println("Finished after $count iterations")
    end

    return reverse(rev_path)
end

ext: jl


text:
function gradient(H::LocalHamiltonian, Ψρs::InfiniteCMPSData, HL = nothing, HR = nothing;
                    kwargs...)
    Ψ, ρL, ρR = Ψρs
    if isnothing(HL)
        HL, = leftenv(H, Ψρs; kwargs...)
    end
    if isnothing(HR)
        HR, = rightenv(H, Ψρs; kwargs...)
    end

    Q = Ψ.Q
    Rs = Ψ.Rs

    gradQ = zero(Q)
    for (coeff, op) in zip(coefficients(H.h), operators(H.h))
        gradQ = gradQ + coeff * localgradientQ(op, Q, Rs, ρL, ρR)
    end
    gradQ += HL*ρR + ρL*HR

    gradRs = zero.(Rs)
    for (coeff, op) in zip(coefficients(H.h), operators(H.h))
        gradRs = gradRs .+ Ref(coeff) .* localgradientRs(op, Q, Rs, ρL, ρR)
    end
    gradRs = gradRs .+ Ref(HL) .* Rs .* Ref(ρR) .+ Ref(ρL) .* Rs .* Ref(HR)

    return gradQ, gradRs
end


text:
module Randomorg_API
using JSON, HTTP
include("Random_numbers.jl")
export generateIntegers, generateIntegerSequences, generateDecimalFractions, generateGaussians, generateStrings, generateUUIDs, generateBlobs

end # module


text:
module Inv

const data_fl = "IntegerArray.txt"

function inv_main()

    num_data = 100_000
    data = Array{Int64,1}(num_data)
    open(data_fl) do file
        num_line = 0
        while !eof(file)
            num_line += 1
            num = parse(Int64, strip(readline(file)))
            data[num_line] = num
        end
    end

    count = inv_count(data)

    print_with_color(:green, "The number of inversions is $(count) !")
end

function inv_count(data::Array{Int64,1})
    if length(data) == 1
        return 0
    else
        ind_m = round(Int64, length(data)/2)
        left = data[1:ind_m]
        right = data[ind_m+1:end]
        l = inv_count(left)
        r = inv_count(right)
        m = inv_merge(left, right)
        return l+r+m
    end

    throw("You can't see me!")
end

function inv_merge(left::Array{Int64,1}, right::Array{Int64,1})
    count = 0
    left_ord = merge_sort(left)
    right_ord = merge_sort(right)

    for l in left_ord, r in right_ord
        if l > r
            count += 1
        elseif l == r
            throw("inv_merge found two equal integer.")
        end
    end

    count
end

#level_stack = 0

function merge_sort(data::Array{Int64,1})
#   global level_stack += 1
#   l = length(data)
#   print_with_color(:blue,"The length of data is $(l)\n")
#   print_with_color(:green, "merge_sort in the stack level $(level_stack).\n")
    num_data = length(data)
    if num_data > 1
        middle = round(Int64, num_data / 2)
        left = merge_sort(data[1:middle])
        right = merge_sort(data[middle+1:end])
        return merge(left,right)::Array{Int64,1}
    elseif num_data == 1
        return data
    else
        throw("input data cann't be empty!")
    end
end

function merge(left::Array{Int64,1}, right::Array{Int64,1})
    num_left = length(left)
    num_right = length(right)
    result = similar(left, num_left+num_right)
    n = 0
    p_left = 1
    p_right = 1
    while n <= (num_left+num_right)
        n += 1
        first_left = left[p_left]
        first_right = right[p_right]

        if first_left < first_right
            result[n] = first_left
            p_left += 1
            if p_left > num_left
                result[n+1:end] = right[p_right:end]
                break
            end
        elseif first_left > first_right
            result[n] = first_right
            p_right += 1
            if p_right > num_right
                result[n+1:end] = left[p_left:end]
                break
            end
        else
            throw("merge found two numbers is same")
        end
    end
    result
end

end


text:
"""
    MutLessThan{T<:Real} <: MOI.AbstractScalarSet

A mutable `LessThan`-like set to test `copy` of indicator set
"""
mutable struct MutLessThan{T<:Real} <: MOI.AbstractScalarSet
    upper::T
    MutLessThan(v::T) where {T<:Real} = new{T}(v)
end

Base.copy(mlt::MutLessThan) = MutLessThan(Base.copy(mlt.upper))

@testset "Sets" begin
    @testset "Copy" begin
        @testset "for $S" for S in [MOI.SOS1, MOI.SOS2]
            s = S([1.0])
            s_copy = copy(s)
            s_copy.weights[1] = 2.0
            @test s.weights[1] == 1.0
        end
        @testset "IndicatorSet" begin
            s1 = MOI.IndicatorSet{MOI.ACTIVATE_ON_ONE}(MOI.LessThan(4.0))
            s2 = MOI.IndicatorSet{MOI.ACTIVATE_ON_ZERO}(MOI.GreaterThan(4.0))
            s1_copy = copy(s1)
            s2_copy = copy(s2)
            @test s1_copy isa MOI.IndicatorSet{MOI.ACTIVATE_ON_ONE}
            @test s1 == s1_copy
            @test s2_copy isa MOI.IndicatorSet{MOI.ACTIVATE_ON_ZERO}
            @test s2 == s2_copy
            s3 = MOI.IndicatorSet{MOI.ACTIVATE_ON_ZERO}(MutLessThan(4.0))
            s3_copy = copy(s3)
            @test s3.set.upper ≈ 4.0
            s3_copy.set.upper = 5.0
            @test s3.set.upper ≈ 4.0
            @test s3_copy.set.upper ≈ 5.0
        end
    end
end


text:
#
# N-queens problem via MiniZinc-Python interface in Julia.
#
# For more info about this Python package, see:
# - https://minizinc-python.readthedocs.io/en/latest/index.html
# - https://gitlab.com/minizinc/minizinc-python
#
# The MiniZinc model is a simple n-queens problem.
#
# This program tests both the model as text string and as a MiniZinc file.
# It assumes there is a file "nqueens.mzn" with the following content
# (but it don't crash if there isn't)
#
# """
#        include "alldifferent.mzn";
#        int: n; %  = 8; % The number of queens.
#
#        array [1..n] of var 1..n: q;
#
#        constraint alldifferent(q);
#        constraint alldifferent(i in 1..n)(q[i] + i);
#        constraint alldifferent(i in 1..n)(q[i] - i);
#        solve :: int_search(q, first_fail, indomain_split) satisfy;
# """
#
# For more MiniZinc models see my MiniZinc page: http://hakank.org/minizinc/
#
#
# Some issues/findings:
#  - the timeout must be a Python datetime.timedelta object
#  - adding the instance size ("n") must be done explicitly with
#    instance.__setitem__("n", n)
#    For some reason instance["n"] don't work.
#  - depending on the number of solutions, printing the results
#    must be handled slightly different.
#
# Note that I have not implemented/checked all the bells&whistles
# of the MiniZinc-Python package.
# This is just a proof of concept program...
#
#
using PyCall

minizinc = pyimport("minizinc")

# For timeout (which is a timedelta object. See below.)
datetime = pyimport("datetime")
timedelta = datetime.timedelta

function nqueens(n=8, all_solutions=true,show_stats=true,show_solutions=true;model_file=nothing,timeout=nothing,free_search=false)

    println("queens($n)")
    Solver = minizinc.Solver
    Instance = minizinc.Instance
    Model = minizinc.Model

    solver = nothing
    try
        # Testing different FlatZinc solvers
        solver = Solver.lookup("gecode")
        # solver = Solver.lookup("picat_sat")
        # solver = Solver.lookup("chuffed")
        # solver = Solver.lookup("jacop")
        # solver = Solver.lookup("izplus")
        # solver = Solver.lookup("optimathsat")
        # solver = Solver.lookup("yuck")
        # solver = Solver.lookup("choco")
        # solver = Solver.lookup("mistral")
        # solver = Solver.lookup("sunnycp")
        # solver = Solver.lookup("or_tools")
        # solver = Solver.lookup("oscar_cbls")

        # println("Solver:", solver)
    catch
        println("Could not find solver!")
        return
    end

    println("solver: ", solver.name)

    model = nothing
    if model_file !== nothing
        model = Model(model_file) # with a MiniZinc file
    else
        # Model as text
        model = Model()
        model.add_string(
        """
        include "alldifferent.mzn";
        int: n; %  = 8; % The number of queens.

        array [1..n] of var 1..n: q;

        constraint alldifferent(q);
        constraint alldifferent(i in 1..n)(q[i] + i);
        constraint alldifferent(i in 1..n)(q[i] - i);
        solve :: int_search(q, first_fail, indomain_split) satisfy;
        """
        )
    end

    instance = Instance(solver, model)
    # instance["n"] = n  # This don't work
    instance.__setitem__("n",n) # This works!

    # Find and print all solution(s)
    result = instance.solve(all_solutions=all_solutions, free_search=free_search,timeout=timeout)

    num_solutions = result.statistics["nSolutions"]
    if num_solutions === nothing
        num_solutions = length(result)
    end
    println("Number of solutions ", num_solutions )
    println("status: ", result.status)
    if num_solutions > 0
        if show_solutions
            if all_solutions
                for i in 1:length(result)
                    println(convert(Array{Int,1},result[i]["q"]))
                end
            else
                println(convert(Array{Int,1},result.solution["q"]))
            end
        end
        if show_stats
            println("\nStatistics:")
            for (s,v) in result.statistics
                println(s, ": ", v)
            end
        end
    else
        println("No solution found!")
    end
    return num_solutions
end

result = nqueens(8,true,false,false);

# Run with a MiniZinc model file
model_file = "nqueens.mzn"
if isfile(model_file)
    result = nqueens(8,true,false,false,model_file=model_file)
else
    println("Cannot find the MiniZinc model $model_file")
end

# The timeout is a datetime.timeout object!
# 10 seconds timeout
timeout = timedelta(seconds=10)

# My standard sizes ...
# (Note: n=500 is slow, but n=501 is faster...)
for n in [8,12,20,100,200,501,1000]
    println("\nn:$n")
    @time num_solutions = nqueens(n,false,false,true,timeout=timeout,free_search=true);
end

max_stars_repo_name: tias/hakank

max_issues_repo_name: tias/hakank

max_forks_repo_name: tias/hakank


text:
isgpu(x) = false
ifgpufree(x) = nothing
function __init__()
    @static if VERSION < v"1.7beta"
      blas = BLAS.vendor()
      IS_OPENBLAS[] = blas == :openblas64 || blas == :openblas
    else
      IS_OPENBLAS[] = occursin("openblas", BLAS.get_config().loaded_libs[1].libname)
    end

    @require CUDA="052768ef-5323-5732-b1bb-66c8b64840ba" include("cuda.jl")
    @require Pardiso="46dd5b70-b6fb-5a00-ae2d-e8fea33afaf2" include("pardiso.jl")
end


text:
module Cuddle

using Reexport

for p in keys(Pkg.installed())
  eval(:(@reexport using $(symbol(p))))
end

end # module


text:
using WebDataset
using Documenter

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

makedocs(;
    modules=[WebDataset],
    authors="Thomas Breuel",
    repo="https://github.com/ThomasBreuel/WebDataset.jl/blob/{commit}{path}#{line}",
    sitename="WebDataset.jl",
    format=Documenter.HTML(;
        prettyurls=get(ENV, "CI", "false") == "true",
        canonical="https://ThomasBreuel.github.io/WebDataset.jl",
        assets=String[],
    ),
    pages=[
        "Home" => "index.md",
    ],
)

deploydocs(;
    repo="github.com/ThomasBreuel/WebDataset.jl",
)


text:
include("../utility.jl")

path = Pkg.dir("MKL") * "/benchmark/b2/"

df = DataFrames.readtable(path*"b2_data_bak.csv", separator = '\t')
N = union(df[:N])
T = union(df[:Type])
imp = union(df[:Implementation])
gen = union(df[:Generic])

for gen in ("sqrt(X)",)
    for t in T

        filter_set = (df[:Type] .== string(t)) & (df[:Generic] .== "sqrt(X)")
        sdf = df[filter_set , :]
        println(sdf)

        imps = union(sdf[:Implementation])
        layers = Layer[]; legend = []; colors = []

        nlayer = 0
        for imp in imps
            linedf = sdf[sdf[:Implementation] .== imp,:]
            if linedf[1,:CPU_mean] > 0
                nlayer += 1
                push!(legend,imp)
                rgb = 0.5+nlayer/20
                imp == "MKL" ?  push!(colors, colorant"deepskyblue") :
                                imp == "BLAS" ? push!(colors, colorant"red") : push!(colors, RGB(rgb,rgb,rgb))
                push!(layers,layer(linedf, x="N", y="CPU_mean", Geom.line, Theme(default_color=colors[nlayer]))[1])
            end
        end

        p = Gadfly.plot(
                layers,
                Scale.x_log10(minvalue=10,maxvalue  =100_000),
                # Scale.y_log10,
                Guide.xlabel("n-dim"),
                Guide.ylabel("relative CPU time"),
                Guide.title("relative CPU time against MKL"),
                Guide.manual_color_key("Legend",
                        legend,
                        colors),
                )

        draw(PNG(path*"$gen"*"_$t.png", 20cm, 10cm), p)
    end
end

# ("1/sqrt(X)",   "BLAS"      ,    t,  nanf        ,   ()          ),
# ("1/sqrt(X)",   "MKL"       ,    t,  mkl_invsqrt!,   (n,a,y)     ),
# ("sqrt(X)",     "VJulia"    ,    t,  vj_invsqrt  ,   (y,a)       ),
# ("sqrt(X)",     "LJulia"    ,    t,  lj_invsqrt  ,   (y,a)       ),
# ("sqrt(X)",     "iLJulia"   ,    t,  ilj_invsqrt ,   (y,a)       ),
# ("sqrt(X)",     "MJulia"    ,    t,  map!        ,   (sqrt,y,a)  ),
# ("sqrt(X)",     "BJulia"    ,    t,  broadcast!  ,   (sqrt,y,a)  ),


text:
module Elly

using Compat
using ProtoBuf
using URIParser
using CRC

import Base: connect, readdir, show, isfile, isdir, islink, stat, filesize, filemode, mtime, mkdir, mkpath,
        mv, rm, abspath, cd, pwd, touch, open, nb_available, cp, joinpath, dirname,
        eof, position, seek, seekend, seekstart, skip, read, write, read!, readbytes, readall, close,
        launch, manage, convert
import ProtoBuf: write_bytes, read_bytes, call_method
import URIParser: URI

export show, convert, URI

export UserGroupInformation, add_token, find_tokens, username

export HDFSClient, HDFSFile, HDFSFileInfo,
        hdfs_server_defaults, hdfs_default_block_size, hdfs_default_replication, hdfs_blocks, hdfs_set_replication,
        hdfs_status, hdfs_capacity, hdfs_capacity_used, hdfs_capacity_remaining, hdfs_renewlease,
        isfile, isdir, islink, stat, filesize, filemode, mtime, atime, du, exists, readdir,
        mkdir, mkpath, touch, mv, rm, abspath, cd, pwd, joinpath, dirname,
        eof, position, seek, seekend, seekstart, skip, nb_available,
        read!, read, write, readbytes, readall, open, close, cp

export YarnClient, YarnNode, YarnApp, YarnAppStatus, YarnAppAttemptStatus, nodecount, nodes, launchcontext, submit, kill, status, attempts, am_rm_token

export YarnAppMaster, register, unregister, kill, can_schedule_mem, can_schedule_cores, container_allocate, container_release, container_start, container_stop, callback

export YarnManager, launch, manage

if VERSION < v"0.5.0-"
typealias Lock RemoteRef
makelock() = RemoteRef()
byte2str(x) = bytestring(x)
else
typealias Lock Channel
makelock() = Channel{Int}(1)
byte2str(x) = String(x)
end

function tstr()
    t = time()
    string(Libc.strftime("%Y-%m-%dT%H:%M:%S",t), Libc.strftime("%z",t)[1:end-2], ":", Libc.strftime("%z",t)[end-1:end])
end

# enable logging only during debugging
#using Logging
##const logger = Logging.configure(filename="elly.log", level=DEBUG)
#const logger = Logging.configure(level=DEBUG)
#macro logmsg(s)
#    quote
#        debug("[", myid(), "-", "] ", $(esc(s)))
#    end
#end
macro logmsg(s)
end
#macro logmsg(s)
#    quote
#        info(tstr(), " [", myid(), "-", "] ", $(esc(s)))
#    end
#end

include("hadoop/hadoop.jl")
using Elly.hadoop
using Elly.hadoop.common
using Elly.hadoop.hdfs
using Elly.hadoop.yarn

const ELLY_CLIENTNAME = "elly"

include("digest.jl")
md5init()

include("ugi.jl")
include("rpc.jl")
include("sasl.jl")
include("envconsts.jl")

include("api_hdfs_base.jl")
include("api_hdfs_io.jl")

include("api_yarn_base.jl")
include("api_yarn_client.jl")
include("api_yarn_appmaster.jl")

include("cluster_manager.jl")

end # module


text:
mutable struct SpMatBuilder{T,S}
    I   :: Array{T}
	J   :: Array{T}
	V   :: Array{S}
	m   :: Int64
	n   :: Int64
	idx :: Int64
end

export getSpMatBuilder,reset!,getSparseMatrix,setNext!,getSparseMatrixTransposed;

function getSpMatBuilder(T::Type,S::Type, m::Int64, n::Int64, nnz::Int64)
	return SpMatBuilder{T,S}(ones(T,nnz),ones(T,nnz),zeros(S,nnz),m,n,1);
end

function reset!(B::SpMatBuilder, m_new::Int64 = B.m, n_new::Int64=B.n)
	B.m = m_new;
	B.n = n_new;
	B.idx = 1;
end

function getSparseMatrix(B::SpMatBuilder)
	idx = B.idx;
	B.I[idx:end] .= 1;
	B.J[idx:end] .= 1;
	B.V[idx:end] .= 0.0;
	return sparse(B.I,B.J,B.V,B.m,B.n);
end

function getSparseMatrixTransposed(B::SpMatBuilder)
	idx = B.idx;
	B.I[idx:end] .= 1;
	B.J[idx:end] .= 1;
	B.V[idx:end] .= 0.0;
	return sparse(B.J,B.I,B.V,B.n,B.m);
end

function setNext!(B::SpMatBuilder{T,S},i::T, j::T, v::S) where {T,S}
idx = B.idx;
if idx <= length(B.I)
	@inbounds B.I[idx] = i;
	@inbounds B.J[idx] = j;
	@inbounds B.V[idx] = v;
	B.idx += 1;
else
	nnz = length(B.I);
	B_new = getSpMatBuilder(T,S, B.m, B.n, 2*nnz)
	B_new.I[1:nnz] .= B.I;
	B_new.J[1:nnz] .= B.J;
	B_new.V[1:nnz] .= B.V;
	B.I = B_new.I;
	B.J = B_new.J;
	B.V = B_new.V;
	setNext!(B,i,j,v);
end
return;
end