Skip to content

Commit

Permalink
Merge pull request #2041 from JuliaOpt/bl/dual_objective_value
Browse files Browse the repository at this point in the history
Add dual_objective_function and update doc links to MOI
  • Loading branch information
blegat committed Aug 24, 2019
2 parents d8806a8 + b282518 commit 3d177c4
Show file tree
Hide file tree
Showing 11 changed files with 40 additions and 33 deletions.
8 changes: 4 additions & 4 deletions docs/src/constraints.md
Expand Up @@ -106,7 +106,7 @@ julia> @constraint(model, 2x + 1 <= 4x + 4)

## [Duality](@id constraint_duality)

JuMP adopts the notion of [conic duality from MOI](http://www.juliaopt.org/MathOptInterface.jl/v0.8.1/apimanual.html#Duals-1).
JuMP adopts the notion of [conic duality from MOI](http://www.juliaopt.org/MathOptInterface.jl/v0.9.1/apimanual/#Duals-1).
For linear programs, a feasible dual on a `>=` constraint is nonnegative and a
feasible dual on a `<=` constraint is nonpositive. If the constraint is an
equality constraint, it depends on which direction is binding.
Expand Down Expand Up @@ -350,13 +350,13 @@ julia> @constraint(model, A * x - b in MOI.Nonnegatives(2))

In addition to the `Nonnegatives` set, MOI defines a number of
other vector-valued sets such as `Nonpositives`. See the
[MOI documentation](http://www.juliaopt.org/MathOptInterface.jl/v0.8.1/apireference/#Sets-1)
[MOI documentation](http://www.juliaopt.org/MathOptInterface.jl/v0.9.1/apireference/#Sets-1)
for more information.

Note also that for the first time we have used an explicit *function-in-set*
description of the constraint. Read more about this representation for
constraints in the
[MOI documentation](http://www.juliaopt.org/MathOptInterface.jl/v0.8.1/apimanual/#Constraints-by-function-set-pairs-1).
[MOI documentation](http://www.juliaopt.org/MathOptInterface.jl/v0.9.1/apimanual/#Constraints-by-function-set-pairs-1).

## Constraints on a single variable

Expand Down Expand Up @@ -440,7 +440,7 @@ julia> @constraint(model, [t, u, x[1], x[2]] in RotatedSecondOrderCone())

In addition to the second order cone and rotated second order cone,
MOI defines a number of other conic sets such as the exponential
and power cones. See the [MathOptInterface documentation](http://www.juliaopt.org/MathOptInterface.jl/v0.8.1/apireference/#Sets-1)
and power cones. See the [MathOptInterface documentation](http://www.juliaopt.org/MathOptInterface.jl/v0.9.1/apireference/#Sets-1)
for more information.

## Constraints on a collection of variables
Expand Down
2 changes: 1 addition & 1 deletion docs/src/extensions.md
Expand Up @@ -22,7 +22,7 @@ Extending JuMP
# TODO: create new bridge
```

See the [bridge section in the MOI manual](http://www.juliaopt.org/MathOptInterface.jl/v0.8/apimanual/#Constraint-bridges-1).
See the [bridge section in the MOI manual](http://www.juliaopt.org/MathOptInterface.jl/v0.9.1/apimanual/#Automatic-reformulation-1).

```@docs
add_bridge
Expand Down
2 changes: 1 addition & 1 deletion docs/src/installation.md
Expand Up @@ -23,7 +23,7 @@ is often more complex. We list below the currently available solvers.
!!! note
This list is open for new contributions. See also
[Interacting with solvers](@ref) and the
[MathOptInterface docs](http://www.juliaopt.org/MathOptInterface.jl/v0.6.1/)
[MathOptInterface docs](http://www.juliaopt.org/MathOptInterface.jl/v0.9.1/)
for more details on how JuMP interacts with solvers. Please get in touch
with any questions about connecting new solvers with JuMP.

Expand Down
2 changes: 1 addition & 1 deletion docs/src/nlp.md
Expand Up @@ -333,7 +333,7 @@ may be expected to be within a factor of 5 of AMPL's.
For some advanced use cases, one may want to directly query the derivatives of a
JuMP model instead of handing the problem off to a solver.
Internally, JuMP implements the `AbstractNLPEvaluator` interface from
[MathOptInterface](http://www.juliaopt.org/MathOptInterface.jl/v0.6.1/apireference.html#NLP-evaluator-methods-1).
[MathOptInterface](http://www.juliaopt.org/MathOptInterface.jl/v0.9.1/apireference/#NLP-evaluator-methods-1).
To obtain an NLP evaluator object from a JuMP model, use `JuMP.NLPEvaluator`.
`JuMP.index` returns the `MOI.VariableIndex` corresponding to a JuMP variable.
`MOI.VariableIndex` itself is a type-safe wrapper for `Int64` (stored in the
Expand Down
5 changes: 4 additions & 1 deletion docs/src/objective.md
Expand Up @@ -17,7 +17,9 @@ To query the objective function from a model, see [`objective_sense`](@ref),

To query the optimal objective value or best known bound after a solve, see
[`objective_value`](@ref) and [`objective_bound`](@ref). These two functions
apply to nonlinear objectives also.
apply to nonlinear objectives also. The optimal value of the
[dual](@ref constraint_duality) objective can be obtained via
[`dual_objective_value`](@ref).


## Reference
Expand All @@ -34,4 +36,5 @@ JuMP.objective_function_type
JuMP.objective_bound
JuMP.objective_value
JuMP.dual_objective_value
```
12 changes: 7 additions & 5 deletions docs/src/solutions.md
Expand Up @@ -31,7 +31,7 @@ see the [Termination statuses](@ref) section below.

Second, we can query the [`primal_status`](@ref) and the [`dual_status`](@ref),
which will tell us what kind of results we have for our primal and dual
solutions. This might be an optimal primal-dual pair, a primal solution without
solutions. This might be an optimal primal-dual pair, a primal solution without
a corresponding dual solution, or a certificate of primal or dual infeasibility.
For more information, see the [Solution statuses](@ref) section below.

Expand Down Expand Up @@ -70,15 +70,15 @@ MOI.ResultStatusCode
```

Common status situations are described in the
[MOI docs](http://www.juliaopt.org/MathOptInterface.jl/v0.8/apimanual/#Common-status-situations-1).
[MOI docs](http://www.juliaopt.org/MathOptInterface.jl/v0.9.1/apimanual/#Common-status-situations-1).

## Obtaining solutions

Provided the primal status is not `MOI.NO_SOLUTION`, the primal solution can
be obtained by calling [`value`](@ref). For the dual solution, the function
is [`dual`](@ref). Calling [`has_values`](@ref) for the primal status and
[`has_duals`](@ref) for the dual solution is an equivalent way to check whether
the status is `MOI.NO_SOLUTION`.
the status is `MOI.NO_SOLUTION`.

It is important to note that if [`has_values`](@ref) or [`has_duals`](@ref)
return false, calls to [`value`](@ref) and [`dual`](@ref) might throw an error
Expand All @@ -95,10 +95,12 @@ The container type (e.g., scalar, vector, or matrix) of the returned solution

The objective value of a solved problem can be obtained via
[`objective_value`](@ref). The best known bound on the optimal objective
value can be obtained via [`objective_bound`](@ref).
value can be obtained via [`objective_bound`](@ref). If the solver supports it,
the value of the dual objective can be obtained via
[`dual_objective_value`](@ref).

The following is a recommended workflow for solving a model and querying the
solution:
solution:
```julia
using JuMP
model = Model()
Expand Down
4 changes: 2 additions & 2 deletions docs/src/solvers.md
Expand Up @@ -56,7 +56,7 @@ the optimizer:
MOI but new ones can be defined and added to the `LazyBridgeOptimizer` used by
JuMP.

See the [MOI documentation](http://www.juliaopt.org/MathOptInterface.jl/v0.8.1/)
See the [MOI documentation](http://www.juliaopt.org/MathOptInterface.jl/v0.9.1/)
for more details on these two MOI layers.

To attach an optimizer to a JuMP model, JuMP needs to create a new empty
Expand Down Expand Up @@ -109,4 +109,4 @@ set_silent
unset_silent
set_parameter
```
```
9 changes: 9 additions & 0 deletions src/objective.jl
Expand Up @@ -24,6 +24,15 @@ Return the objective value after a call to `optimize!(model)`.
"""
objective_value(model::Model)::Float64 = MOI.get(model, MOI.ObjectiveValue())

"""
dual_objective_value(model::Model)
Return the value of the objective of the dual problem after a call to
`optimize!(model)`. Throws `MOI.UnsupportedAttribute{MOI.DualObjectiveValue}` if
the solver does not support this attribute.
"""
dual_objective_value(model::Model)::Float64 = MOI.get(model, MOI.DualObjectiveValue())

"""
objective_sense(model::Model)::MathOptInterface.OptimizationSense
Expand Down
2 changes: 2 additions & 0 deletions test/generate_and_solve.jl
Expand Up @@ -71,6 +71,7 @@ using JuMP
@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)
Expand Down Expand Up @@ -225,6 +226,7 @@ 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 5.0 == @inferred JuMP.dual_objective_value(m)

@test MOI.FEASIBLE_POINT == @inferred JuMP.dual_status(m)
@test -1.0 == @inferred JuMP.dual(c1)
Expand Down
24 changes: 8 additions & 16 deletions test/model.jl
Expand Up @@ -14,21 +14,12 @@ using JuMP

using Test

using MathOptInterface
const MOI = MathOptInterface
const MOIT = MOI.Test
const MOIU = MOI.Utilities

# Simple LP model not supporting Interval
@MOIU.model(SimpleLPModel,
(),
(MOI.EqualTo, MOI.GreaterThan, MOI.LessThan),
(),
(),
(),
(MOI.ScalarAffineFunction,),
(),
())
MOIU.@model(
SimpleLPModel,
(), (MOI.EqualTo, MOI.GreaterThan, MOI.LessThan), (), (),
(), (MOI.ScalarAffineFunction,), (), ()
)

struct Optimizer
a::Int
Expand Down Expand Up @@ -63,6 +54,7 @@ function test_model()
c = @constraint(model, x 0)
@objective(model, Max, x)
@test_throws err JuMP.objective_value(model)
@test_throws err JuMP.dual_objective_value(model)
@test_throws err JuMP.objective_bound(model)
@test_throws err JuMP.value(x)
@test_throws err JuMP.value(c)
Expand Down Expand Up @@ -164,8 +156,8 @@ function test_model()

@testset "UniversalFallback" begin
m = Model()
MOI.set(m, MOIT.UnknownModelAttribute(), 1)
@test MOI.get(m, MOIT.UnknownModelAttribute()) == 1
MOI.set(m, MOI.Test.UnknownModelAttribute(), 1)
@test MOI.get(m, MOI.Test.UnknownModelAttribute()) == 1
end

@testset "Bridges" begin
Expand Down
3 changes: 1 addition & 2 deletions test/nonnegative_bridge.jl
Expand Up @@ -10,8 +10,7 @@

# This file contains an example bridge used for tests.

using MathOptInterface
const MOI = MathOptInterface
using JuMP
const MOIB = MOI.Bridges
const MOIBC = MOI.Bridges.Constraint

Expand Down

0 comments on commit 3d177c4

Please sign in to comment.