Part # 1
I was interested in getting the costates. The costates are also known as the lagrange multipliers or dual variables. I looked through the MathProgBase docs and found this function called getconstduals does that give me my lagrange multipliers?
It does not seems like it. If I am solving a the Bryson Denham problem, I can match the analytical solution for the controls and states
Duality. MOI aims to define consistent conventions for duals across problem classes. In some cases, the signs may differ from the current MPB conventions.
Another possibility (just guessing), but maybe the sign change could be due to an internal rewrite of the constraints in a canonical form. If you have, say, @constraint(m, x == 1) in your code, it could be that while setting up the internal model, the constraint is rewritten as 1 - x == 0, with the Lagrange multiplier (dual variable) acting on 1 - x, while you were maybe expecting the Lagrange multiplier to act on x - 1.
JuMP defines getdual methods for ConstraintRefs as well by the way; I don’t think you should have to access the internal model:
julia> methods(getdual)
# 7 methods for generic function "getdual":
getdual(c::JuMP.ConstraintRef{JuMP.Model,JuMP.GenericRangeConstraint{JuMP.NonlinearExprData}}) in JuMP at /Users/twan/code/julia/RigidBodyDynamics/v0.6/JuMP/src/nlp.jl:56
getdual(c::JuMP.ConstraintRef{JuMP.Model,JuMP.SDConstraint}) in JuMP at /Users/twan/code/julia/RigidBodyDynamics/v0.6/JuMP/src/JuMP.jl:715
getdual(c::JuMP.ConstraintRef{JuMP.Model,JuMP.GenericSOCConstraint{JuMP.GenericNormExpr{2,Float64,JuMP.Variable}}}) in JuMP at /Users/twan/code/julia/RigidBodyDynamics/v0.6/JuMP/src/JuMP.jl:676
getdual(c::JuMP.ConstraintRef{JuMP.Model,JuMP.GenericRangeConstraint{JuMP.GenericAffExpr{Float64,JuMP.Variable}}}) in JuMP at /Users/twan/code/julia/RigidBodyDynamics/v0.6/JuMP/src/JuMP.jl:586
getdual(v::JuMP.Variable) in JuMP at /Users/twan/code/julia/RigidBodyDynamics/v0.6/JuMP/src/JuMP.jl:466
getdual(x::AbstractArray) in JuMP at /Users/twan/code/julia/RigidBodyDynamics/v0.6/JuMP/src/JuMPContainer.jl:109
getdual(x::JuMP.JuMPContainer) in JuMP at /Users/twan/code/julia/RigidBodyDynamics/v0.6/JuMP/src/JuMPContainer.jl:114
So you can do e.g.:
julia> m = Model(solver = GurobiSolver(OutputFlag = 0));
julia> @variable(m, x);
julia> @constraint(m, c, x == 1)
x = 1
julia> @objective(m, :Min, x)
x
julia> solve(m)
:Optimal
julia> getdual(c)
1.0
using JuMP, Gurobi
m = Model(solver = GurobiSolver(OutputFlag = false))
@variable(m, x)
@objective(m, :Min, x)
@constraint(m, c, x >= 1)
solve(m)
getdual(c)
we get 1.0, but for the same code with the @objective line replaced by @objective(m, :Max, -x) (really, the same problem), we get -1.0.
The Duality chapter in Boyd and Vandenberghe, starts with the canonical form (5.1), i.e. a minimization. I would expect that for a maximization problem, JuMP would automatically turn maximizing -x into minimizing x to fit (5.1), and then return the duals for that problem (so that the dual would be the same in both cases above). Maybe this is part of the ‘consistent conventions for duals’ mentioned in the post.