Skip to content

Commit

Permalink
Added functions simplex_iterations(), barrier_iterations() and node_c…
Browse files Browse the repository at this point in the history
…ount() (jump-dev#2201)

* Addded getter functions simplex_iterations(), barrier_iterations() and node_count()

* Removed return type of getter functions, @inferred in tests.

* Update JuMP.jl

* Added documentation for getter functions.

* Update solutions.md

Co-authored-by: Oscar Dowson <[email protected]>
  • Loading branch information
vrngupta53 and odow authored Apr 6, 2020
1 parent a29caf9 commit fb52b47
Show file tree
Hide file tree
Showing 3 changed files with 89 additions and 1 deletion.
18 changes: 17 additions & 1 deletion docs/src/solutions.md
Original file line number Diff line number Diff line change
Expand Up @@ -133,15 +133,28 @@ end
[MathOptInterface](https://www.juliaopt.org/MathOptInterface.jl/v0.9.10/) defines a large
number of model attributes that can be queried. Examples include
[`MOI.RelativeGap`](https://www.juliaopt.org/MathOptInterface.jl/v0.9.10/apireference/#MathOptInterface.RelativeGap) and
[`MOI.SimplexIterations`](https://www.juliaopt.org/MathOptInterface.jl/v0.9.10/apireference/#MathOptInterface.SimplexIterations). Some attributes can be directly accessed by getter functions like [`objective_bound`](@ref) and [`relative_gap`](@ref).
[`MOI.SimplexIterations`](https://www.juliaopt.org/MathOptInterface.jl/v0.9.10/apireference/#MathOptInterface.SimplexIterations).

Some attributes can be directly accessed by getter functions. These include
- [`objective_bound`](@ref)
- [`relative_gap`](@ref)
- [`simplex_iterations`](@ref)
- [`barrier_iterations`](@ref)
- [`node_count`](@ref)

To query these attributes, use:
```julia
using JuMP
model = Model()
# ...
optimize!(model)

@show relative_gap(model)
# or
@show MOI.get(model, MOI.RelativeGap())

@show simplex_iterations(model)
# or
@show MOI.get(model, MOI.SimplexIterations())
```

Expand Down Expand Up @@ -278,4 +291,7 @@ OptimizeNotCalled
MOI.optimize!
JuMP.result_count
JuMP.relative_gap
JuMP.simplex_iterations
JuMP.barrier_iterations
JuMP.node_count
```
34 changes: 34 additions & 0 deletions src/JuMP.jl
Original file line number Diff line number Diff line change
Expand Up @@ -661,6 +661,40 @@ function time_limit_sec(model::Model)
return MOI.get(model, MOI.TimeLimitSec())
end

"""
simplex_iterations(model::Model)
Gets the cumulative number of simplex iterations during the most-recent optimization.
Solvers must implement `MOI.SimplexIterations()` to use this function.
"""
function simplex_iterations(model::Model)
return MOI.get(model, MOI.SimplexIterations())
end

"""
barrier_iterations(model::Model)
Gets the cumulative number of barrier iterations during the most recent optimization.
Solvers must implement `MOI.BarrierIterations()` to use this function.
"""
function barrier_iterations(model::Model)
return MOI.get(model, MOI.BarrierIterations())
end

"""
node_count(model::Model)
Gets the total number of branch-and-bound nodes explored during the most recent
optimization in a Mixed Integer Program.
Solvers must implement `MOI.NodeCount()` to use this function.
"""
function node_count(model::Model)
return MOI.get(model, MOI.NodeCount())
end

# Abstract base type for all scalar types
# The subtyping of `AbstractMutable` will allow calls of some `Base` functions
# to be redirected to a method in MA that handles type promotion more carefuly
Expand Down
38 changes: 38 additions & 0 deletions test/generate_and_solve.jl
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,10 @@ using JuMP
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)
Expand All @@ -78,6 +82,9 @@ using JuMP
@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
Expand All @@ -101,6 +108,9 @@ using JuMP
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)

Expand All @@ -120,6 +130,9 @@ using JuMP
@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
Expand Down Expand Up @@ -161,6 +174,9 @@ using JuMP
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)
Expand All @@ -175,6 +191,10 @@ using JuMP
@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)
Expand Down Expand Up @@ -219,6 +239,9 @@ using JuMP
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)
Expand All @@ -238,6 +261,9 @@ using JuMP
@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
Expand Down Expand Up @@ -281,6 +307,9 @@ using JuMP
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)

Expand All @@ -298,6 +327,9 @@ using JuMP
@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
Expand Down Expand Up @@ -348,6 +380,9 @@ using JuMP
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)

Expand All @@ -371,6 +406,9 @@ using JuMP
@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

Expand Down

0 comments on commit fb52b47

Please sign in to comment.