From 869d850c7bf58dddd2b844752161f9a62712fa16 Mon Sep 17 00:00:00 2001 From: Miles Lubin Date: Tue, 13 Jun 2017 23:43:39 -0400 Subject: [PATCH 01/83] begin rewrite of docs, big changes to SolverInterface --- docs/make.jl | 3 +- docs/src/solverinterface.md | 61 ++++++ src/HighLevelInterface/HighLevelInterface.jl | 7 - src/MathProgBase.jl | 2 - src/SolverInterface/SolverInterface.jl | 135 ++++++------- src/SolverInterface/attributes.jl | 190 +++++++++++++++++++ 6 files changed, 309 insertions(+), 89 deletions(-) create mode 100644 docs/src/solverinterface.md create mode 100644 src/SolverInterface/attributes.jl diff --git a/docs/make.jl b/docs/make.jl index 9ba588e..8637700 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -4,7 +4,8 @@ makedocs( format = :html, sitename = "MathProgBase", pages = [ - "index.md", + "Introduction" => "index.md", + "Solver Interface" => "solverinterface.md" ] ) diff --git a/docs/src/solverinterface.md b/docs/src/solverinterface.md new file mode 100644 index 0000000..fba1b37 --- /dev/null +++ b/docs/src/solverinterface.md @@ -0,0 +1,61 @@ +# Solver Interface + +```@meta +CurrentModule = MathProgBase +``` + +```@docs +AbstractMathProgModel +AbstractMathProgSolver +``` + +## Basic Methods + +```@docs +optimize! +freemodel! +``` + +## Attributes + +These are used to get and set properties of the model. + +```@docs +AbstractAttribute +cangetattribute +getattribute +cansetattribute +setattribute! +``` + +### Scalar Attributes + +```@docs +ObjectiveValue +ObjectiveBound +RelativeGap +SolveTime +Sense +SimplexIterations +BarrierIterations +NodeCount +RawSolver +ResultCount +``` + +### Variable Attributes + +```@docs +VariableStart +VariableDualStart +VariableResult +``` + + +## Termination Status + +The `TerminationStatus` attribute is meant to explain the reason why the solver stopped executing. The value of the attribute is of type `TerminationStatusCode`. + +```@docs +TerminationStatusCode +``` diff --git a/src/HighLevelInterface/HighLevelInterface.jl b/src/HighLevelInterface/HighLevelInterface.jl index ddaad0a..7952a64 100644 --- a/src/HighLevelInterface/HighLevelInterface.jl +++ b/src/HighLevelInterface/HighLevelInterface.jl @@ -1,8 +1,3 @@ -module HighLevelInterface - -using ..SolverInterface -using ..MathProgBase - function warn_no_inf(T) if !(isinf(typemin(T)) && isinf(typemax(T))) Base.warn_once("Element type $T does not have an infinite value. Note that this may artifically introduce ranged (two-sided) constraints. To avoid this, consider casting the problem data to Float64.") @@ -12,5 +7,3 @@ end include("linprog.jl") include("mixintprog.jl") include("quadprog.jl") - -end diff --git a/src/MathProgBase.jl b/src/MathProgBase.jl index b545e42..c216f95 100644 --- a/src/MathProgBase.jl +++ b/src/MathProgBase.jl @@ -3,10 +3,8 @@ __precompile__() module MathProgBase include(joinpath(dirname(@__FILE__),"SolverInterface","SolverInterface.jl")) -using .SolverInterface include(joinpath(dirname(@__FILE__),"HighLevelInterface","HighLevelInterface.jl")) -using .HighLevelInterface export linprog, mixintprog, quadprog, buildlp, solvelp end diff --git a/src/SolverInterface/SolverInterface.jl b/src/SolverInterface/SolverInterface.jl index f978c7d..3a7d9e3 100644 --- a/src/SolverInterface/SolverInterface.jl +++ b/src/SolverInterface/SolverInterface.jl @@ -1,92 +1,69 @@ -module SolverInterface - using Base.Meta -const methods_by_tag = Dict{Symbol,Vector{Symbol}}() - -macro define_interface(args) - @assert args.head == :block - code = quote end - for line in args.args - (isexpr(line, :line) && continue) - (isa(line,Symbol) || isexpr(line,:tuple)) || error("Unexpected code in block") - if isa(line,Symbol) - fname = line - tags = [] - else - @assert isexpr(line,:tuple) - fname = line.args[1] - tags = line.args[2:end] - end - func = esc(fname) - code = quote - $code - $(func)() = throw(MethodError($(func),())) - function $(func)(::Int) - q = Any[1] - return q[1] # infer Any return type, workaround for julia issue #9479 - end - end - for t in tags - t = quot(t) - code = quote - $code - if haskey(methods_by_tag,$t) - push!(methods_by_tag[$t],$(quot(fname))) - else - methods_by_tag[$t] = [$(quot(fname))] - end - end - end - push!(code.args, Expr(:export, func)) - end - return code -end +export AbstractMathProgModel, AbstractMathProgSolver + +# not sure if this should still be here +rewrap_methods = [:getobjbound, + :getobjgap, + :getrawsolver, + :getsolvetime, + ] +""" + AbstractMathProgModel + +Abstract supertype which represents a solver's +in-memory representation of an optimization problem. +""" abstract type AbstractMathProgModel end -export AbstractMathProgModel # immutable type which we dispatch solvers on +""" + AbstractMathProgSolver + +Abstract supertype for "solver" objects. A solver is a lightweight object used for selecting solvers and parameters. It does not store any instance data. +""" abstract type AbstractMathProgSolver end -export AbstractMathProgSolver - -# create dummy method to define function so that we can attach methods in other modules -# these are the common methods for AbstractMathProgModel -@define_interface begin - getsolution - getobjval - optimize! - status - getobjbound, rewrap - getobjgap, rewrap - getrawsolver, rewrap - getsolvetime, rewrap - setsense! - getsense - numvar - numconstr - freemodel! - setvartype! - getvartype - loadproblem! - setwarmstart! -end -# solver parameters, may be implemented by AbstractMathProgModel or AbstractMathProgSolver -@define_interface begin - setparameters! -end +# basic methods methods for AbstractMathProgModel -include("LinearQuadratic.jl") -include("callbacks.jl") -include("Nonlinear.jl") -include("Conic.jl") +""" + optimize!(m::AbstractMathProgModel) -# Solver conversion routines -include("conic_to_lpqp.jl") -include("lpqp_to_conic.jl") -include("nonlinear_to_lpqp.jl") +Start the solution procedure. +""" +function optimize! end + +""" + freemodel!(m::AbstractMathProgModel) + +Release any resources and memory used by the model. Note that the +Julia garbage collector takes care of this automatically, but +automatic collection cannot always be forced. This method is useful for more +precise control of resources, especially in the case of commercial solvers +with licensing restrictions on the number of concurrent runs. +Users must discard the model object after this method is invoked. +""" +function freemodel! end +# TODO +function loadproblem! end -end + + +# these could change to attributes that can be set on a model *or solver* +# solver parameters, may be implemented by AbstractMathProgModel or AbstractMathProgSolver +function setparameters! end + +include("attributes.jl") + +#include("LinearQuadratic.jl") +#include("callbacks.jl") +#include("Nonlinear.jl") +#include("Conic.jl") + +# Solver conversion routines +#include("conic_to_lpqp.jl") +#include("lpqp_to_conic.jl") +#include("nonlinear_to_lpqp.jl") diff --git a/src/SolverInterface/attributes.jl b/src/SolverInterface/attributes.jl new file mode 100644 index 0000000..78012a3 --- /dev/null +++ b/src/SolverInterface/attributes.jl @@ -0,0 +1,190 @@ +""" + AbstractAttribute + +Abstract supertype for attribute objects that can be used +to set or get attributes (properties) of the model. +""" +abstract type AbstractAttribute end + +""" + getattribute(m::AbstractMathProgModel, attr::Type{T} where T <: AbstractAttribute) + +Return an attribute of the model `m` specified by attribute type `attr`. + +# Examples + + getattribute(m, ObjectiveValue) +""" +function getattribute end + +""" + cangetattribute(m::AbstractMathProgModel, attr::Type{T} where T <: AbstractAttribute)::Bool + +Return a `Bool` indicating whether the model `m` currently has a value for +the attributed specified by attribute type `attr`. +""" +function cangetattribute end + +""" + cansetattribute(m::AbstractMathProgModel, attr::Type{T} where T <: AbstractAttribute)::Bool + +Return a `Bool` indicating whether the model `m` will accept a +`setattribute!` call for the attributed specified by attribute type `attr`. +""" +function cansetattribute end + +""" + setattribute!(m::AbstractMathProgModel, attr::Type{T} where T <: AbstractAttribute, ...) + +Set an attribute of the model `m` specified by attribute type `attr`. +""" +function setattribute! end + +# Scalar attributes +""" + ObjectiveValue + +The objective value of the best primal result vector found by the solver. +""" +struct ObjectiveValue <: AbstractAttribute end + +""" + ObjectiveBound + +The best known bound on the optimal objective value. +""" +struct ObjectiveBound <: AbstractAttribute end + +""" + RelativeGap + +The final relative optimality gap as optimization terminated. That is, ``\\frac{|b-f|}{|f|}``, where ``b`` is the best bound and ``f`` is the best feasible objective value. +""" +struct RelativeGap <: AbstractAttribute end + +""" + SolveTime + +The total elapsed solution time (in seconds) as reported by the solver. +""" +struct SolveTime <: AbstractAttribute end + +""" + Sense + +The optimization sense of the model. Valid values are `:Min` and `:Max`. +""" +struct Sense <: AbstractAttribute end + +""" + SimplexIterations + +The cumulative number of simplex iterations during the optimization process. In particular, for a MIP the total simplex iterations for all nodes. +""" +struct SimplexIterations <: AbstractAttribute end + +""" + BarrierIterations + +The cumulative number of barrier iterations during the optimization process. +""" +struct BarrierIterations <: AbstractAttribute end + +""" + NodeCount + +The total number of branch-and-bound nodes explored. +""" +struct NodeCount <: AbstractAttribute end + +""" + RawSolver + +An object that may be used to access a solver-specific API for this model. +""" +struct RawSolver <: AbstractAttribute end + +""" + ResultCount + +The number of results available. +""" +struct ResultCount <: AbstractAttribute end + + +# Variable attributes + +""" + VariableStart + +An initial assignment of the variables that the solver may use +to warm-start the solve. +""" +struct VariableStart <: AbstractAttribute end + +""" + VariableDualStart + +An initial assignment of the variable duals that the solver may use +to warm-start the solve. +""" +struct VariableDualStart <: AbstractAttribute end + +""" + VariableResult{N} + +The assignment to the primal variables in result `N`. If `N` is omitted, it is interpreted as 1. +""" +struct VariableResult{N} <: AbstractAttribute end + + +function getsolution end +function getobjval end + + +function setvartype! end +function getvartype end +function loadproblem! end +function setwarmstart! end + + +# Termination status + +struct TerminationStatus <: AbstractAttribute end + +""" + TerminationStatusCode + +An Enum of possible values for the `TerminationStatus` attribute. This attribute is meant to explain the reason why the solver stopped executing. + +# OK + +These are generally OK statuses. + + * `Success`: the algorithm ran successfully and has a result. This includes cases where the algorithm converges to an infeasible point (NLP) or converges to a solution of a homogeneous self-dual problem and has a certificate of primal/dual infeasibility. + + * `AlmostSuccess`: the algorithm *almost* ran successfully (e.g., to relaxed convergence tolerances) and has a result. + + * `InfeasibleNoResult`: the algorithm stopped because it decided that the problem is infeasible but does not have a result to return. + + * `UnboundedNoResult`: the algorithm stopped because it decided that the problem is unbounded but does not have a result to return. + + * `InfeasibleOrUnbounded`: the algorithm stopped because it decided that the problem is infeasible or unbounded; no result is available. This occasionally happens during MIP presolve. + +# Limits + +The solver stopped because of some user-defined limit. +To be documented: `IterationLimit`, `TimeLimit`, `NodeLimit`, `SolutionLimit`, `MemoryLimit`, `ObjectiveLimit`, `NormLimit`, `OtherLimit`. + +# Problematic + +This group of statuses means that something unexpected or problematic happened. + + * `SlowProgress`: the algorithm stopped because it was unable to continue making progress towards the solution. `AlmostSuccess` should be used if there is additional information that relaxed convergence tolerances are satisfied. + +To be documented: `NumericalError`, `InvalidModel`, `InvalidOption`, `Interrupted`, `OtherError`. + +""" +@enum TerminationStatusCode Success AlmostSuccess InfeasibleNoResult UnboundedNoResult InfeasibleOrUnbounded IterationLimit TimeLimit NodeLimit SolutionLimit MemoryLimit ObjectiveLimit NormLimit OtherLimit SlowProgress NumericalError InvalidModel InvalidOption Interrupted OtherError + + From 7cce0147f545c67668499d54acb4bc6f938c795c Mon Sep 17 00:00:00 2001 From: Miles Lubin Date: Wed, 14 Jun 2017 10:02:23 -0400 Subject: [PATCH 02/83] more work --- src/SolverInterface/attributes.jl | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/src/SolverInterface/attributes.jl b/src/SolverInterface/attributes.jl index 78012a3..ef9ff17 100644 --- a/src/SolverInterface/attributes.jl +++ b/src/SolverInterface/attributes.jl @@ -6,19 +6,25 @@ to set or get attributes (properties) of the model. """ abstract type AbstractAttribute end +# TODO: +# in-place getters + """ - getattribute(m::AbstractMathProgModel, attr::Type{T} where T <: AbstractAttribute) + getattribute(m::AbstractMathProgModel, attr::AbstractAttribute) Return an attribute of the model `m` specified by attribute type `attr`. # Examples - getattribute(m, ObjectiveValue) + getattribute(m, ObjectiveValue()) + getattribute(m, VariableResult()) + getattribute(m, VariableResult(5)) + getattribute(m, OtherAttribute("something specific to cplex")) """ function getattribute end """ - cangetattribute(m::AbstractMathProgModel, attr::Type{T} where T <: AbstractAttribute)::Bool + cangetattribute(m::AbstractMathProgModel, attr::AbstractAttribute)::Bool Return a `Bool` indicating whether the model `m` currently has a value for the attributed specified by attribute type `attr`. @@ -26,7 +32,7 @@ the attributed specified by attribute type `attr`. function cangetattribute end """ - cansetattribute(m::AbstractMathProgModel, attr::Type{T} where T <: AbstractAttribute)::Bool + cansetattribute(m::AbstractMathProgModel, attr::AbstractAttribute)::Bool Return a `Bool` indicating whether the model `m` will accept a `setattribute!` call for the attributed specified by attribute type `attr`. @@ -34,7 +40,7 @@ Return a `Bool` indicating whether the model `m` will accept a function cansetattribute end """ - setattribute!(m::AbstractMathProgModel, attr::Type{T} where T <: AbstractAttribute, ...) + setattribute!(m::AbstractMathProgModel, attr::AbstractAttribute, ...) Set an attribute of the model `m` specified by attribute type `attr`. """ @@ -55,12 +61,14 @@ The best known bound on the optimal objective value. """ struct ObjectiveBound <: AbstractAttribute end + +struct RelativeGapAttr <: AbstractAttribute end """ RelativeGap The final relative optimality gap as optimization terminated. That is, ``\\frac{|b-f|}{|f|}``, where ``b`` is the best bound and ``f`` is the best feasible objective value. """ -struct RelativeGap <: AbstractAttribute end +const RelativeGap = RelativeGapAttr() """ SolveTime @@ -131,11 +139,15 @@ to warm-start the solve. struct VariableDualStart <: AbstractAttribute end """ - VariableResult{N} + VariableResult The assignment to the primal variables in result `N`. If `N` is omitted, it is interpreted as 1. """ -struct VariableResult{N} <: AbstractAttribute end +struct VariableResult <: AbstractAttribute + N::Int +end + +# VarType? function getsolution end From c7234e72ef86885ff6fec2d443b97e3a8dcf4331 Mon Sep 17 00:00:00 2001 From: Miles Lubin Date: Wed, 14 Jun 2017 13:54:53 -0400 Subject: [PATCH 03/83] beginning of sets --- docs/src/solverinterface.md | 15 ++++++ src/SolverInterface/SolverInterface.jl | 1 + src/SolverInterface/sets.jl | 66 ++++++++++++++++++++++++++ 3 files changed, 82 insertions(+) create mode 100644 src/SolverInterface/sets.jl diff --git a/docs/src/solverinterface.md b/docs/src/solverinterface.md index fba1b37..60550a3 100644 --- a/docs/src/solverinterface.md +++ b/docs/src/solverinterface.md @@ -16,6 +16,21 @@ optimize! freemodel! ``` +## Sets + +How to add constraints. +```@docs +addconstraint! +``` + +List of sets. +```@docs +NonNegative +NonPositive +Zero +Interval +``` + ## Attributes These are used to get and set properties of the model. diff --git a/src/SolverInterface/SolverInterface.jl b/src/SolverInterface/SolverInterface.jl index 3a7d9e3..76c2a5e 100644 --- a/src/SolverInterface/SolverInterface.jl +++ b/src/SolverInterface/SolverInterface.jl @@ -56,6 +56,7 @@ function loadproblem! end # solver parameters, may be implemented by AbstractMathProgModel or AbstractMathProgSolver function setparameters! end +include("sets.jl") include("attributes.jl") #include("LinearQuadratic.jl") diff --git a/src/SolverInterface/sets.jl b/src/SolverInterface/sets.jl new file mode 100644 index 0000000..828db08 --- /dev/null +++ b/src/SolverInterface/sets.jl @@ -0,0 +1,66 @@ + + +""" + AbstractSet + +Abstract supertype for set objects used to encode constraints. +""" +abstract type AbstractSet end + + +""" + NonNegative(dim) + +The nonnegative orthant ``\\{ x \\in \\mathbb{R}^n : x \\ge 0 \\}`` where the dimension ``n`` is specified by the field `dim`. +""" +struct NonNegative <: AbstractSet + dim::Int +end + +""" + NonPositive(dim) + +The nonpositive orthant ``\\{ x \\in \\mathbb{R}^n : x \\le 0 \\}`` where the dimension ``n`` is specified by the field `dim`. +""" +struct NonPositive <: AbstractSet + dim::Int +end + +""" + Zero(dim) + +The set ``\\{0\\}^n`` where the dimension ``n`` is specified by the field `dim`. +""" +struct Zero <: AbstractSet + dim::Int +end + +dimension(s::Union{NonNegative,NonPositive,Zero}) = s.dim + +""" + Interval(lower,upper) + +The set ``[l,u] \\subseteq \\mathbb{R}^n`` where ``l`` and ``u`` are specified by `lower` and `upper`, respectively. We allow `lower` and `upper` to be `-Inf` or `Inf`, in which case the set is interpreted as a one-sided interval. +""" +struct Interval{T} <: AbstractSet + lower::T + upper::T +end + +dimension(s::Interval) = 1 + +""" + addconstraint!(m::AbstractMathProgModel, b, a_varidx, a_coef, Q_vari, Q_varj, Q_val, S::AbstractSet) + +Add the constraint +```math +a^Tx + b + \\frac{1}{2}x^TQx \\in S +``` +where ``a`` is a sparse vector specified in tuple form by +`a_varidx`, and `a_val`; ``b`` is a scalar; +the symmetric matrix ``Q_i`` is defined by the triplets in `Q_vari`, `Q_varj`, +`Q_val`; and the set ``S`` is defined by `S`. + +Duplicate indices in either `a_varidx` or `Q_vari` and `Q_varj` are accepted and will be summed together. Off-diagonal entries of ``Q`` will be mirrored, so either the upper triangular or lower triangular entries of ``Q`` should be provided. If entries for both ``(i,j)`` and ``(j,i)`` are provided, these are considered duplicate terms. +""" +function addconstraint! end From 8f0662b2fb6de6787442f81cf710e5a7db1d46a8 Mon Sep 17 00:00:00 2001 From: Miles Lubin Date: Wed, 14 Jun 2017 14:14:31 -0400 Subject: [PATCH 04/83] argument naming --- src/SolverInterface/sets.jl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/SolverInterface/sets.jl b/src/SolverInterface/sets.jl index 828db08..9e1de79 100644 --- a/src/SolverInterface/sets.jl +++ b/src/SolverInterface/sets.jl @@ -50,16 +50,16 @@ end dimension(s::Interval) = 1 """ - addconstraint!(m::AbstractMathProgModel, b, a_varidx, a_coef, Q_vari, Q_varj, Q_val, S::AbstractSet) + addconstraint!(m::AbstractMathProgModel, b, a_varidx, a_coef, Q_vari, Q_varj, Q_coef, S::AbstractSet) Add the constraint ```math a^Tx + b + \\frac{1}{2}x^TQx \\in S ``` where ``a`` is a sparse vector specified in tuple form by -`a_varidx`, and `a_val`; ``b`` is a scalar; +`a_varidx`, and `a_coef`; ``b`` is a scalar; the symmetric matrix ``Q_i`` is defined by the triplets in `Q_vari`, `Q_varj`, -`Q_val`; and the set ``S`` is defined by `S`. +`Q_coef`; and the set ``S`` is defined by `S`. Duplicate indices in either `a_varidx` or `Q_vari` and `Q_varj` are accepted and will be summed together. Off-diagonal entries of ``Q`` will be mirrored, so either the upper triangular or lower triangular entries of ``Q`` should be provided. If entries for both ``(i,j)`` and ``(j,i)`` are provided, these are considered duplicate terms. """ From 514810cb10f53dd8dd35d19c5b216e3f891f53ea Mon Sep 17 00:00:00 2001 From: Miles Lubin Date: Wed, 14 Jun 2017 14:22:00 -0400 Subject: [PATCH 05/83] more coherent interface --- src/SolverInterface/sets.jl | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/src/SolverInterface/sets.jl b/src/SolverInterface/sets.jl index 9e1de79..45fbd53 100644 --- a/src/SolverInterface/sets.jl +++ b/src/SolverInterface/sets.jl @@ -50,17 +50,30 @@ end dimension(s::Interval) = 1 """ + addconstraint!(m::AbstractMathProgModel, b, a_constridx, a_varidx, a_coef, Q_constridx, Q_vari, Q_varj, Q_coef, S::AbstractSet) + +Add the constraint +```math +Ax + b + q \\in S +``` +where ``A`` is a sparse vector specified in triplet form by +`a_constridx`, `a_varidx`, and `a_coef`; ``b`` is a vector; +``q`` is a vector with entry `k` equal to ``\\frac{1}{2}x^TQ_kx`` +where the symmetric matrix ``Q_k`` is defined by the triplets in `Q_vari`, `Q_varj`, +`Q_coef` for which `Q_constridx` equals `k`; and the set ``S`` is defined by `S`. + +Duplicate indices in either ``A`` or a ``Q`` matrix are accepted and will be summed together. Off-diagonal entries of ``Q`` will be mirrored, so either the upper triangular or lower triangular entries of ``Q`` should be provided. If entries for both ``(i,j)`` and ``(j,i)`` are provided, these are considered duplicate terms. + addconstraint!(m::AbstractMathProgModel, b, a_varidx, a_coef, Q_vari, Q_varj, Q_coef, S::AbstractSet) +A specialized version of `addconstraint!` for one-dimensional sets. Add the constraint ```math a^Tx + b + \\frac{1}{2}x^TQx \\in S ``` where ``a`` is a sparse vector specified in tuple form by `a_varidx`, and `a_coef`; ``b`` is a scalar; -the symmetric matrix ``Q_i`` is defined by the triplets in `Q_vari`, `Q_varj`, +the symmetric matrix ``Q`` is defined by the triplets in `Q_vari`, `Q_varj`, `Q_coef`; and the set ``S`` is defined by `S`. - -Duplicate indices in either `a_varidx` or `Q_vari` and `Q_varj` are accepted and will be summed together. Off-diagonal entries of ``Q`` will be mirrored, so either the upper triangular or lower triangular entries of ``Q`` should be provided. If entries for both ``(i,j)`` and ``(j,i)`` are provided, these are considered duplicate terms. """ function addconstraint! end From 32c68f091899024cba930cf4b8d4418d79cd6171 Mon Sep 17 00:00:00 2001 From: Miles Lubin Date: Wed, 14 Jun 2017 14:30:11 -0400 Subject: [PATCH 06/83] tidy notation --- src/SolverInterface/sets.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/SolverInterface/sets.jl b/src/SolverInterface/sets.jl index 45fbd53..bd43670 100644 --- a/src/SolverInterface/sets.jl +++ b/src/SolverInterface/sets.jl @@ -54,11 +54,11 @@ dimension(s::Interval) = 1 Add the constraint ```math -Ax + b + q \\in S +Ax + b + q(x) \\in S ``` where ``A`` is a sparse vector specified in triplet form by `a_constridx`, `a_varidx`, and `a_coef`; ``b`` is a vector; -``q`` is a vector with entry `k` equal to ``\\frac{1}{2}x^TQ_kx`` +``q(x)`` is a vector with component ``(q(x))_k`` defined to be ``\\frac{1}{2}x^TQ_kx`` where the symmetric matrix ``Q_k`` is defined by the triplets in `Q_vari`, `Q_varj`, `Q_coef` for which `Q_constridx` equals `k`; and the set ``S`` is defined by `S`. From 855cd86d24bb8007fba50bf5e3d557b716308ea1 Mon Sep 17 00:00:00 2001 From: Miles Lubin Date: Wed, 14 Jun 2017 15:36:25 -0400 Subject: [PATCH 07/83] variable bounds and variable constraints --- docs/src/solverinterface.md | 9 +++++- src/SolverInterface/attributes.jl | 48 +++++++++++++++++++++++++++++-- src/SolverInterface/sets.jl | 43 ++++++++++++++++++++++----- 3 files changed, 89 insertions(+), 11 deletions(-) diff --git a/docs/src/solverinterface.md b/docs/src/solverinterface.md index 60550a3..1bb5bae 100644 --- a/docs/src/solverinterface.md +++ b/docs/src/solverinterface.md @@ -29,6 +29,8 @@ NonNegative NonPositive Zero Interval +Integers +Binaries ``` ## Attributes @@ -62,7 +64,12 @@ ResultCount ```@docs VariableStart -VariableDualStart +VariableLowerBoundDualStart +VariableUpperBoundDualStart +VariableLowerBound +VariableLowerBoundVector +VariableUpperBound +VariableUpperBoundVector VariableResult ``` diff --git a/src/SolverInterface/attributes.jl b/src/SolverInterface/attributes.jl index ef9ff17..387c922 100644 --- a/src/SolverInterface/attributes.jl +++ b/src/SolverInterface/attributes.jl @@ -131,12 +131,54 @@ to warm-start the solve. struct VariableStart <: AbstractAttribute end """ - VariableDualStart + VariableLowerBoundDualStart -An initial assignment of the variable duals that the solver may use +An initial assignment of the variable lower-bound duals that the solver may use to warm-start the solve. """ -struct VariableDualStart <: AbstractAttribute end +struct VariableLowerBoundDualStart <: AbstractAttribute end + +""" + VariableUpperBoundDualStart + +An initial assignment of the variable upper-bound duals that the solver may use +to warm-start the solve. +""" +struct VariableUpperBoundDualStart <: AbstractAttribute end + + +""" + VariableLowerBound(i) + +Lower-bound constraint on variable index `i`. `-Inf` is valid as no bound. +""" +struct VariableLowerBound <: AbstractAttribute + i::Int +end + +""" + VariableLowerBoundVector + +Lower-bound constraint vector for the variables. `-Inf` is valid as no bound. +""" +struct VariableLowerBoundVector <: AbstractAttribute end + +""" + VariableUpperBound(i) + +Upper-bound constraint vector for the variables. `Inf` is valid as no bound. +""" +struct VariableUpperBound <: AbstractAttribute + i::Int +end + +""" + VariableUpperBoundVector + +Upper-bound constraints on variable index `i`. `Inf` is valid as no bound. +""" +struct VariableUpperBoundVector <: AbstractAttribute end + """ VariableResult diff --git a/src/SolverInterface/sets.jl b/src/SolverInterface/sets.jl index bd43670..d3996a8 100644 --- a/src/SolverInterface/sets.jl +++ b/src/SolverInterface/sets.jl @@ -9,33 +9,32 @@ abstract type AbstractSet end """ - NonNegative(dim) + NonNegative(n) -The nonnegative orthant ``\\{ x \\in \\mathbb{R}^n : x \\ge 0 \\}`` where the dimension ``n`` is specified by the field `dim`. +The nonnegative orthant ``\\{ x \\in \\mathbb{R}^n : x \\ge 0 \\}`` where the dimension ``n`` is specified by the field `n`. """ struct NonNegative <: AbstractSet dim::Int end """ - NonPositive(dim) + NonPositive(n) -The nonpositive orthant ``\\{ x \\in \\mathbb{R}^n : x \\le 0 \\}`` where the dimension ``n`` is specified by the field `dim`. +The nonpositive orthant ``\\{ x \\in \\mathbb{R}^n : x \\le 0 \\}`` where the dimension ``n`` is specified by the field `n`. """ struct NonPositive <: AbstractSet dim::Int end """ - Zero(dim) + Zero(n) -The set ``\\{0\\}^n`` where the dimension ``n`` is specified by the field `dim`. +The set ``\\{0\\}^n`` where the dimension ``n`` is specified by the field `n`. """ struct Zero <: AbstractSet dim::Int end -dimension(s::Union{NonNegative,NonPositive,Zero}) = s.dim """ Interval(lower,upper) @@ -49,6 +48,27 @@ end dimension(s::Interval) = 1 +""" + Integers(n) + +The set of integers ``\\mathbb{Z}^n``. +""" +struct Integers <: AbstractSet + dim::Int +end + +""" + Binaries(n) + +The set of binary vectors ``\\{0,1\\}^n``. +""" +struct Binaries <: AbstractSet + dim::Int +end + + +dimension(s::Union{NonNegative,NonPositive,Zero,Integers,Binaries}) = s.dim + """ addconstraint!(m::AbstractMathProgModel, b, a_constridx, a_varidx, a_coef, Q_constridx, Q_vari, Q_varj, Q_coef, S::AbstractSet) @@ -75,5 +95,14 @@ where ``a`` is a sparse vector specified in tuple form by `a_varidx`, and `a_coef`; ``b`` is a scalar; the symmetric matrix ``Q`` is defined by the triplets in `Q_vari`, `Q_varj`, `Q_coef`; and the set ``S`` is defined by `S`. + + addconstraint!(m::AbstractMathProgModel, varidx, S::AbstractSet) + +A specialized version of `addconstraint!` for constraints on subsets of variables. +Add the constraint +```math +x_{varidx} \\in S +``` +where `varidx` specifies the indices of the subvector of `x`. """ function addconstraint! end From dbf2b42dba261a2611c5f3907056e7376bc82fe7 Mon Sep 17 00:00:00 2001 From: jac0320 Date: Wed, 14 Jun 2017 17:18:10 -0400 Subject: [PATCH 08/83] Added draft documentation with documenter --- docs/make.jl | 8 +- docs/mkdoc.yml | 9 ++ docs/src/choosingsolver.md | 10 ++ docs/src/index.md | 18 ++- docs/src/linearprog.md | 11 ++ docs/src/mixedintprog.md | 5 + docs/src/quadprog.md | 9 ++ docs/src/solverinterface.md | 9 +- src/HighLevelInterface/linprog.jl | 177 +++++++++++++++++++++++++ src/HighLevelInterface/mixintprog.jl | 52 +++++++- src/HighLevelInterface/quadprog.jl | 84 +++++++++++- src/SolverInterface/SolverInterface.jl | 2 +- src/SolverInterface/attributes.jl | 2 - 13 files changed, 383 insertions(+), 13 deletions(-) create mode 100644 docs/mkdoc.yml create mode 100644 docs/src/choosingsolver.md create mode 100644 docs/src/linearprog.md create mode 100644 docs/src/mixedintprog.md create mode 100644 docs/src/quadprog.md diff --git a/docs/make.jl b/docs/make.jl index 8637700..009c642 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -5,7 +5,11 @@ makedocs( sitename = "MathProgBase", pages = [ "Introduction" => "index.md", - "Solver Interface" => "solverinterface.md" + "Linear Programming" => "linearprog.md", + "Mixed-Integer Programming" => "mixedintprog.md", + "Quadratic Programming" => "quadprog.md", + "Solver Interface" => "solverinterface.md", + "Choosing Solver" => "choosingsolver.md" ] ) @@ -14,6 +18,6 @@ deploydocs( target = "build", osname = "linux", julia = "0.6", - deps = nothing, + deps = Deps.pip("pygments", "mkdocs", "python-markdown-math"), make = nothing ) diff --git a/docs/mkdoc.yml b/docs/mkdoc.yml new file mode 100644 index 0000000..4585041 --- /dev/null +++ b/docs/mkdoc.yml @@ -0,0 +1,9 @@ +# ... +markdown_extensions: + - mdx_math + # ... + +extra_javascript: + - https://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS_HTML + - assets/mathjaxhelper.js +# ... diff --git a/docs/src/choosingsolver.md b/docs/src/choosingsolver.md new file mode 100644 index 0000000..e1b9edd --- /dev/null +++ b/docs/src/choosingsolver.md @@ -0,0 +1,10 @@ +# Choosing Solvers + +Solvers and solver-specific parameters are specified by [`AbstractMathProgSolver`](@ref) objects, which are provided by particular solver packages. For example, the `Clp` package exports a `ClpSolver` object, which can be passed to [`linprog`](@ref) as follows:: + +```julia + using Clp + linprog([-1,0],[2 1],'<',1.5, ClpSolver()) +``` + +Options are passed as keyword arguments, for example, `ClpSolver(LogLevel=1)`. See the [Clp](https://github.com/mlubin/Clp.jl), [Cbc](https://github.com/mlubin/Cbc.jl), [GLPKMathProgInterface](https://github.com/JuliaOpt/GLPKMathProgInterface.jl), and [Gurobi](https://github.com/JuliaOpt/Gurobi.jl) packages for more information. diff --git a/docs/src/index.md b/docs/src/index.md index 9baeaca..6799e2a 100644 --- a/docs/src/index.md +++ b/docs/src/index.md @@ -1 +1,17 @@ -# MathProgBase documentation +# MathProgBase + +Solver-independent functions and low-level interfaces for Mathematical Programming + +`MathProgBase.jl` provides high-level one-shot functions for linear and mixed-integer programming, as well as a solver-independent low-level interface for implementing advanced techniques that require efficiently solving a sequence of linear programming problems. + +To use MathProgBase, an external solver must be installed. See [Choosing Solvers](@ref). + +```@contents +pages=[ + "linearprog.md", + "mixedintprog.md", + "quadprog.md", + "solverinterface.md", + "choosingsolver.md" + ] +``` diff --git a/docs/src/linearprog.md b/docs/src/linearprog.md new file mode 100644 index 0000000..c048304 --- /dev/null +++ b/docs/src/linearprog.md @@ -0,0 +1,11 @@ +# Linear Programming + +```@meta + CurrentModule = MathProgBase +``` + +```@docs +linprog +buildlp +solvelp +``` diff --git a/docs/src/mixedintprog.md b/docs/src/mixedintprog.md new file mode 100644 index 0000000..5f37b59 --- /dev/null +++ b/docs/src/mixedintprog.md @@ -0,0 +1,5 @@ +# Mixed-integer Programming + +```@docs +mixintprog +``` diff --git a/docs/src/quadprog.md b/docs/src/quadprog.md new file mode 100644 index 0000000..8a7600a --- /dev/null +++ b/docs/src/quadprog.md @@ -0,0 +1,9 @@ +# Quadratic Programming + +```@meta + CurrentModule = MathProgBase +``` + +```@docs +quadprog +``` diff --git a/docs/src/solverinterface.md b/docs/src/solverinterface.md index 60550a3..1bb5bae 100644 --- a/docs/src/solverinterface.md +++ b/docs/src/solverinterface.md @@ -29,6 +29,8 @@ NonNegative NonPositive Zero Interval +Integers +Binaries ``` ## Attributes @@ -62,7 +64,12 @@ ResultCount ```@docs VariableStart -VariableDualStart +VariableLowerBoundDualStart +VariableUpperBoundDualStart +VariableLowerBound +VariableLowerBoundVector +VariableUpperBound +VariableUpperBoundVector VariableResult ``` diff --git a/src/HighLevelInterface/linprog.jl b/src/HighLevelInterface/linprog.jl index c383056..85ce378 100644 --- a/src/HighLevelInterface/linprog.jl +++ b/src/HighLevelInterface/linprog.jl @@ -29,6 +29,50 @@ function no_lp_solver() """) end +""" + buildlp(c::InputVector, A::AbstractMatrix, sense::InputVector, b::InputVector, lb::InputVector, ub::InputVector, solver::AbstractMathProgSolver) + + Builds the linear programming problem as defined in [`linprog`](@ref) and accepts the following arguments: + +* ``c`` is the objective vector, always in the sense of minimization + +* ``A`` is the constraint matrix + +* ``sense`` is a vector of constraint sense characters ``'<'``, ``'='``, and ``'>'`` + +* ``b`` is the right-hand side vector + +* ``l`` is the vector of lower bounds on the variables + +* ``u`` is the vector of upper bounds on the variables, and + +* ``solver`` specifies the desired solver, see [Choosing Solvers](@ref). + +A scalar is accepted for the ``b``, ``sense``, ``l``, and ``u`` arguments, in which case its value is replicated. The values ``-Inf`` and ``Inf`` are interpreted to mean that there is no corresponding lower or upper bound. + +This variant of [`buildlp`](@ref) allows to specify two-sided linear constraints (also known as range constraints) similar to [`linprog`](@ref), and accepts the following arguments: + + buildlp(c::InputVector, A::AbstractMatrix, rowlb::InputVector, rowub::InputVector, lb::InputVector, ub::InputVector, solver::AbstractMathProgSolver) + +* ``c`` is the objective vector, always in the sense of minimization + +* ``A`` is the constraint matrix + +* ``rowlb`` is the vector of row lower bounds + +* ``rowub`` is the vector of row upper bounds + +* ``lb`` is the vector of lower bounds on the variables + +* ``ub`` is the vector of upper bounds on the variables, and + +* ``solver`` specifies the desired solver, see [Choosing Solvers](@ref). + +A scalar is accepted for the ``l``, ``u``, ``lb``, and ``ub`` arguments, in which case its value is replicated. The values ``-Inf`` and ``Inf`` are interpreted to mean that there is no corresponding lower or upper bound. Equality constraints are specified by setting the row lower and upper bounds to the same value. + +The [`buildlp`](@ref) function returns an [`AbstractLinearQuadraticModel`](@ref) that can be input to [`solvelp`](@ref) in order to obtain a solution. +""" + function buildlp(c::InputVector, A::AbstractMatrix, rowlb::InputVector, rowub::InputVector, lb::InputVector, ub::InputVector, solver::AbstractMathProgSolver) m = LinearQuadraticModel(solver) nrow,ncol = size(A) @@ -73,6 +117,23 @@ function buildlp(c::InputVector, A::AbstractMatrix, rowlb::InputVector, rowub::I return m end +""" +Solves the linear programming problem as defined in [`linprog`](@ref) and accepts the following argument: + +* `m` is an [`AbstractLinearQuadraticModel`](@ref) (e.g., as returned by [`buildlp`](@ref)). + +The [`solvelp`](@ref) function returns an instance of the type:: + +```julia +type LinprogSolution + status + objval + sol + attrs +end +``` + +""" function solvelp(m) optimize!(m) stat = status(m) @@ -101,7 +162,123 @@ function solvelp(m) return LinprogSolution(stat, nothing, [], Dict()) end end +""" + + linprog(c::InputVector, A::AbstractMatrix, rowlb::InputVector, rowub::InputVector, lb::InputVector, ub::InputVector, solver::AbstractMathProgSolver) + +This function allows one to specify two-sided linear constraints (also known as range constraints) to solve the linear programming problem: + +```math +\\begin{align*} +\\text{min}_{x} \\quad & c^{T} x \\\\ +\\text{s.t.} \\quad & rowlb \\leq A^{T} x \\leq rowub \\\\ + \\quad & l \\leq x \\leq u \\\\ + +\\end{align*} +``` + +where: + +* ``c`` is the objective vector, always in the sense of minimization + +* ``A`` is the constraint matrix + +* ``rowlb`` is the vector of row lower bounds + +* ``rowub`` is the vector of row upper bounds + +* ``lb`` is the vector of lower bounds on the variables + +* ``ub`` is the vector of upper bounds on the variables, and + +* ``solver`` specifies the desired solver, see [Choosing Solvers](@ref). + +A scalar is accepted for the ``l``, ``u``, ``rowlb``, and ``rowub`` arguments, in which case its value is replicated. The values ``-Inf`` and ``Inf`` are interpreted to mean that there is no corresponding lower or upper bound. Equality constraints are specified by setting the row lower and upper bounds to the same value. + +A variant usage of this function is to consider the linear programming problem in the following form, + + linprog(c::InputVector, A::AbstractMatrix, sense::InputVector, b::InputVector, lb::InputVector, ub::InputVector, solver::AbstractMathProgSolver) + +```math +\\begin{align*} +\\text{min}_{x} \\quad & c^{T}x \\\\ +\\text{s.t.} \\quad & A_{i}^{T} \\, \\text{sense}_{i} \\, b_{i} \\quad \\forall i \\\\ + \\quad & l \\leq x \\leq u +\\end{align*} +``` + +where: + +* ``c``: is the objective vector, always in the sense of minimization + +* ``A``: is the constraint matrix, with rows a_i (viewed as column-oriented vectors) + +* sense: is a vector of constraint sense characters ``<``, ``=``, and ``>`` + +* ``b``: is the right-hand side vector + +* ``l``: is the vector of lower bounds on the variables + +* ``u`` is the vector of upper bounds on the variables, and solver specifies the desired solver, see [Choosing Solvers](@ref). + + +A shortened version is defined as:: + + linprog(c, A, lb, ub, solver) = linprog(c, A, lb, ub, 0, Inf, solver) + +!!! note + The function [`linprog`](@ref) calls two independent functions for building and solving the linear programming problem, namely [`buildlp`](@ref) and [`solvelp`](@ref). + +The [`linprog`](@ref) function returns an instance of the type:: + +```julia + type LinprogSolution + status + objval + sol + attrs + end +``` + +where `status` is a termination status symbol, one of `:Optimal`, `:Infeasible`, `:Unbounded`, `:UserLimit` (iteration limit or timeout), `:Error` (and maybe others). + +If `status` is `:Optimal`, the other members have the following values: + +* `objval` -- optimal objective value +* `sol` -- primal solution vector +* `attrs` -- a dictionary that may contain other relevant attributes such as: + + - `redcost` -- dual multipliers for active variable bounds (zero if inactive) + - `lambda` -- dual multipliers for active linear constraints (equalities are always active) + +If `status` is `:Infeasible`, the `attrs` member will contain an `infeasibilityray` if available; similarly for `:Unbounded` problems, `attrs` will contain an `unboundedray` if available. + + - `colbasis` -- optimal simplex basis statuses for the variables (columns) if available. Possible values are `:NonbasicAtLower`, `:NonbasicAtUpper`, `:Basic`, and `:Superbasic` (not yet implemented by any solvers) + - `rowbasis` -- optimal simplex basis statuses for the constraints (rows) if available (not yet implemented by any solvers) + +For example, we can solve the two-dimensional problem (see ``test/linprog.jl``): + +```math + \\begin{align*} + \\text{min}_{x,y} \\quad & -x \\\\ + \\text{s.t.} \\quad & 2x + y \\leq 1.5 \\\\ + \\quad & x \\geq 0, y \\geq 0 + \\end{align*} +``` + +```julia + using MathProgBase, Clp + + sol = linprog([-1,0],[2 1],'<',1.5, ClpSolver()) + if sol.status == :Optimal + println("Optimal objective value is \$(sol.objval)") + println("Optimal solution vector is: [\$(sol.sol[1]), \$(sol.sol[2])]") + else + println("Error: solution status \$(sol.status)") + end +``` +""" function linprog(c::InputVector, A::AbstractMatrix, rowlb::InputVector, rowub::InputVector, lb::InputVector, ub::InputVector, solver::AbstractMathProgSolver) m = buildlp(c, A, rowlb, rowub, lb, ub, solver) return solvelp(m) diff --git a/src/HighLevelInterface/mixintprog.jl b/src/HighLevelInterface/mixintprog.jl index a9f1b24..b5137c7 100644 --- a/src/HighLevelInterface/mixintprog.jl +++ b/src/HighLevelInterface/mixintprog.jl @@ -19,6 +19,52 @@ function no_mip_solver() """) end +""" + + mixintprog(c::InputVector, A::AbstractMatrix, sense::InputVector, b::InputVector, vartypes::SymbolInputVector, lb::InputVector, ub::InputVector, solver::AbstractMathProgSolver) + +Solves the same optimization problem as [`linprog`](@ref) above, except variables are additionally constrained to take only integer values if the corresponding entry in the `varypes` vector is the symbol `:Int`. Continuous variables are indicated by the value `:Cont`, binary variables should be specified by `:Bin`, semicontinuous by `:SemiCont`, and semi-integer by `:SemiInt`. + +A scalar is accepted for the ``sense``, ``b``, ``vartypes``, ``lb``, and ``ub`` arguments, in which case its value is replicated. The values ``-Inf`` and ``Inf`` are interpreted to mean that there is no corresponding lower or upper bound. + +The [`mixintprog`](@ref) function returns an instance of the type:: + + type MixintprogSolution + status + objval + sol + attrs + end + +where `status` takes the same values as with [`linprog`](@ref). + +If `status` does not indicate error or infeasiblity, the other members have the following values: + +* `objval` -- optimal objective value +* `sol` -- primal solution vector +* `attrs` -- a dictionary that may contain other relevant attributes such as: + + - `objbound` -- Best known lower bound on the objective value + +Analogous shortened and range-constraint versions are available as well. + +We can solve a [binary knapsack problem](http://en.wikipedia.org/wiki/Knapsack_problem) + +```math +\\begin{align*} + \\text{max} \\, & 5x_1 + 3x_2 + 2x_3 + 7x_4 + 4x_5 \\\\ + \\text{s.t.} & 2x_1 + 8x_2 + 4x_3 + 2x_4 + 5x_5 \\leq 10 \\\\ + & (x_1, x_2, x_3, x_4, x_5) \\in \\{0,1\\}^5 +\\end{align*} +``` + +with the following code + +```julia + mixintprog(-[5.,3.,2.,7.,4.],[2. 8. 4. 2. 5.],'<',10,:Int,0,1,CbcSolver()) +``` + +""" function mixintprog(c::InputVector, A::AbstractMatrix, rowlb::InputVector, rowub::InputVector, vartypes::SymbolInputVector, lb::InputVector, ub::InputVector, solver::AbstractMathProgSolver) m = LinearQuadraticModel(solver) nrow,ncol = size(A) @@ -29,7 +75,7 @@ function mixintprog(c::InputVector, A::AbstractMatrix, rowlb::InputVector, rowub lb = expandvec(lb, ncol) ub = expandvec(ub, ncol) vartypes = expandvec(vartypes, ncol) - + # rowlb is allowed to be vector of senses if eltype(rowlbtmp) == Char realtype = eltype(rowubtmp) @@ -56,7 +102,7 @@ function mixintprog(c::InputVector, A::AbstractMatrix, rowlb::InputVector, rowub rowlb = rowlbtmp rowub = rowubtmp end - + loadproblem!(m, A, lb, ub, c, rowlb, rowub, :Min) setvartype!(m, vartypes) optimize!(m) @@ -77,5 +123,3 @@ mixintprog(c,A,rowlb,rowub,vartypes) = no_mip_solver() mixintprog(c::InputVector, A::AbstractMatrix, rowlb::InputVector, rowub::InputVector, vartypes::SymbolInputVector, lb::InputVector, ub::InputVector) = no_mip_solver() export mixintprog - - diff --git a/src/HighLevelInterface/quadprog.jl b/src/HighLevelInterface/quadprog.jl index e30d158..b4ca08d 100644 --- a/src/HighLevelInterface/quadprog.jl +++ b/src/HighLevelInterface/quadprog.jl @@ -17,6 +17,86 @@ function no_qp_solver() """) end +""" + + quadprog(c::InputVector, Q::AbstractMatrix, A::AbstractMatrix, sense::InputVector, b::InputVector, lb::InputVector, ub::InputVector, solver::AbstractMathProgSolver) + +Solves the quadratic programming problem: + +```math + \\begin{align*} + \\text{min}_{x} \\quad & \\frac{1}{2}x^TQx + c^Tx \\\\ + \\text{s.t.} \\quad & a_i^Tx \\, \\text{sense}_i \\, b_i \\forall \\quad i \\\\ + \\quad & l \\leq x \\leq u \\\\ + \\end{align*} +``` + +where: + +* ``c`` is the objective vector, always in the sense of minimization + +* ``Q`` is the Hessian matrix of the objective + +* ``A`` is the constraint matrix, with rows :math:`a_i` (viewed as column-oriented vectors) + +* ``sense`` is a vector of constraint sense characters ``<``, ``=``, and ``>`` + +* ``b`` is the right-hand side vector + +* ``l`` is the vector of lower bounds on the variables + +* ``u`` is the vector of upper bounds on the variables, and + +* ``solver`` specifies the desired solver, see [Choosing Solvers](@ref). + +A scalar is accepted for the ``b``, ``sense``, ``l``, and ``u`` arguments, in which case its value is replicated. The values ``-Inf`` and ``Inf`` are interpreted to mean that there is no corresponding lower or upper bound. + +.. note:: + Quadratic programming solvers extensively exploit the sparsity of the Hessian matrix ``Q`` and the constraint matrix ``A``. While both dense and sparse matrices are accepted, for large-scale problems sparse matrices should be provided if permitted by the problem structure. + +The [`quadprog`](@ref) function returns an instance of the type:: + + type QuadprogSolution + status + objval + sol + attrs + end + +where `status` is a termination status symbol, one of `:Optimal`, `:Infeasible`, `:Unbounded`, `:UserLimit` (iteration limit or timeout), `:Error` (and maybe others). + +If `status` is `:Optimal`, the other members have the following values: + +* `objval` -- optimal objective value +* `sol` -- primal solution vector +* `attrs` -- a dictionary that may contain other relevant attributes (not currently used). + +Analogous shortened and range-constraint versions are available as well. + +We can solve the three-dimensional QP (see `test/quadprog.jl`): + +```math + \\begin{align*} + \\text{min}_{x,y,z} \\quad & x^2+y^2+z^2+xy+yz \\\\ + \\text{s.t.} \\quad & x + 2y + 3z \\geq 4 \\\\ + \\quad & x + y \\geq 1 + \\end{align*} +``` + +```julia + + using MathProgBase, Ipopt + + sol = quadprog([0., 0., 0.],[2. 1. 0.; 1. 2. 1.; 0. 1. 2.],[1. 2. 3.; 1. 1. 0.],'>',[4., 1.],-Inf,Inf, IpoptSolver()) + if sol.status == :Optimal + println("Optimal objective value is \$(sol.objval)") + println("Optimal solution vector is: [\$(sol.sol[1]), \$(sol.sol[2]), \$(sol.sol[3])]") + else + println("Error: solution status \$(sol.status)") + end +``` + +""" function quadprog(c::InputVector, Q::AbstractMatrix, A::AbstractMatrix, rowlb::InputVector, rowub::InputVector, lb::InputVector, ub::InputVector, solver::AbstractMathProgSolver) m = LinearQuadraticModel(solver) nrow,ncol = size(A) @@ -26,7 +106,7 @@ function quadprog(c::InputVector, Q::AbstractMatrix, A::AbstractMatrix, rowlb::I rowubtmp = expandvec(rowub, nrow) lb = expandvec(lb, ncol) ub = expandvec(ub, ncol) - + # rowlb is allowed to be vector of senses if eltype(rowlbtmp) == Char realtype = eltype(rowubtmp) @@ -54,7 +134,7 @@ function quadprog(c::InputVector, Q::AbstractMatrix, A::AbstractMatrix, rowlb::I rowlb = rowlbtmp rowub = rowubtmp end - + loadproblem!(m, A, lb, ub, c, rowlb, rowub, :Min) setquadobj!(m, Q) optimize!(m) diff --git a/src/SolverInterface/SolverInterface.jl b/src/SolverInterface/SolverInterface.jl index 76c2a5e..f86d47e 100644 --- a/src/SolverInterface/SolverInterface.jl +++ b/src/SolverInterface/SolverInterface.jl @@ -1,6 +1,6 @@ using Base.Meta -export AbstractMathProgModel, AbstractMathProgSolver +export AbstractMathProgModel, AbstractMathProgSolver # not sure if this should still be here rewrap_methods = [:getobjbound, diff --git a/src/SolverInterface/attributes.jl b/src/SolverInterface/attributes.jl index ef9ff17..786f6e8 100644 --- a/src/SolverInterface/attributes.jl +++ b/src/SolverInterface/attributes.jl @@ -198,5 +198,3 @@ To be documented: `NumericalError`, `InvalidModel`, `InvalidOption`, `Interrupte """ @enum TerminationStatusCode Success AlmostSuccess InfeasibleNoResult UnboundedNoResult InfeasibleOrUnbounded IterationLimit TimeLimit NodeLimit SolutionLimit MemoryLimit ObjectiveLimit NormLimit OtherLimit SlowProgress NumericalError InvalidModel InvalidOption Interrupted OtherError - - From 9e72b7f811d4bfebd640fe992e205a4ff70d9818 Mon Sep 17 00:00:00 2001 From: jac0320 Date: Wed, 14 Jun 2017 17:28:33 -0400 Subject: [PATCH 09/83] Added draft documentation with documenter --- docs/src/index.md | 12 +----------- src/HighLevelInterface/linprog.jl | 2 +- 2 files changed, 2 insertions(+), 12 deletions(-) diff --git a/docs/src/index.md b/docs/src/index.md index 6799e2a..267db76 100644 --- a/docs/src/index.md +++ b/docs/src/index.md @@ -2,16 +2,6 @@ Solver-independent functions and low-level interfaces for Mathematical Programming -`MathProgBase.jl` provides high-level one-shot functions for linear and mixed-integer programming, as well as a solver-independent low-level interface for implementing advanced techniques that require efficiently solving a sequence of linear programming problems. +[MathProgBase.jl](https://github.com/JuliaOpt/MathProgBase.jl) provides high-level one-shot functions for linear and mixed-integer programming, as well as a solver-independent low-level interface for implementing advanced techniques that require efficiently solving a sequence of linear programming problems. To use MathProgBase, an external solver must be installed. See [Choosing Solvers](@ref). - -```@contents -pages=[ - "linearprog.md", - "mixedintprog.md", - "quadprog.md", - "solverinterface.md", - "choosingsolver.md" - ] -``` diff --git a/src/HighLevelInterface/linprog.jl b/src/HighLevelInterface/linprog.jl index 85ce378..a0fb3f6 100644 --- a/src/HighLevelInterface/linprog.jl +++ b/src/HighLevelInterface/linprog.jl @@ -32,7 +32,7 @@ end """ buildlp(c::InputVector, A::AbstractMatrix, sense::InputVector, b::InputVector, lb::InputVector, ub::InputVector, solver::AbstractMathProgSolver) - Builds the linear programming problem as defined in [`linprog`](@ref) and accepts the following arguments: +Builds the linear programming problem as defined in [`linprog`](@ref) and accepts the following arguments: * ``c`` is the objective vector, always in the sense of minimization From cbf0d0493a7e3aaa19b24e91511f5256f4a49ec9 Mon Sep 17 00:00:00 2001 From: Miles Lubin Date: Wed, 14 Jun 2017 17:33:21 -0400 Subject: [PATCH 10/83] variable and constraint references --- docs/src/solverinterface.md | 29 +++++++++-- src/SolverInterface/SolverInterface.jl | 2 + src/SolverInterface/attributes.jl | 51 ++++++++++-------- src/SolverInterface/constraints.jl | 72 ++++++++++++++++++++++++++ src/SolverInterface/sets.jl | 37 ------------- src/SolverInterface/variables.jl | 48 +++++++++++++++++ 6 files changed, 177 insertions(+), 62 deletions(-) create mode 100644 src/SolverInterface/constraints.jl create mode 100644 src/SolverInterface/variables.jl diff --git a/docs/src/solverinterface.md b/docs/src/solverinterface.md index 1bb5bae..fe609d0 100644 --- a/docs/src/solverinterface.md +++ b/docs/src/solverinterface.md @@ -16,13 +16,32 @@ optimize! freemodel! ``` -## Sets +## Variables + +```@docs +VariableReference +candelete(::AbstractMathProgModel,::VariableReference) +isactive(::AbstractMathProgModel,::VariableReference) +delete!(::AbstractMathProgModel,::VariableReference) +addvariables! +addvariable! +``` + +## Constraints How to add constraints. ```@docs +ConstraintReference +candelete(::AbstractMathProgModel,::ConstraintReference) +isactive(::AbstractMathProgModel,::ConstraintReference) +delete!(::AbstractMathProgModel,::ConstraintReference) addconstraint! ``` +## Sets + + + List of sets. ```@docs NonNegative @@ -62,15 +81,17 @@ ResultCount ### Variable Attributes +These attributes are associated with variables. Calls to `getattribute` and `setattribute!` should include a single `VariableReference` or a vector of `VariableReference` objects. + ```@docs VariableStart VariableLowerBoundDualStart VariableUpperBoundDualStart VariableLowerBound -VariableLowerBoundVector VariableUpperBound -VariableUpperBoundVector -VariableResult +VariablePrimal +VariableLowerBoundDual +VariableUpperBoundDual ``` diff --git a/src/SolverInterface/SolverInterface.jl b/src/SolverInterface/SolverInterface.jl index 76c2a5e..ce245cf 100644 --- a/src/SolverInterface/SolverInterface.jl +++ b/src/SolverInterface/SolverInterface.jl @@ -56,6 +56,8 @@ function loadproblem! end # solver parameters, may be implemented by AbstractMathProgModel or AbstractMathProgSolver function setparameters! end +include("variables.jl") +include("constraints.jl") include("sets.jl") include("attributes.jl") diff --git a/src/SolverInterface/attributes.jl b/src/SolverInterface/attributes.jl index 387c922..a28435b 100644 --- a/src/SolverInterface/attributes.jl +++ b/src/SolverInterface/attributes.jl @@ -17,12 +17,19 @@ Return an attribute of the model `m` specified by attribute type `attr`. # Examples getattribute(m, ObjectiveValue()) - getattribute(m, VariableResult()) - getattribute(m, VariableResult(5)) + getattribute(m, VariableResult(), ref) + getattribute(m, VariableResult(5), [ref1,ref2]) getattribute(m, OtherAttribute("something specific to cplex")) """ function getattribute end +""" + getattribute!(output, m::AbstractMathProgModel, attr::AbstractAttribute) + +An in-place version of `getattribute!`. Return an attribute of the model `m` specified by attribute type `attr` into output vector `attr`. +""" +function getattribute! end + """ cangetattribute(m::AbstractMathProgModel, attr::AbstractAttribute)::Bool @@ -148,47 +155,49 @@ struct VariableUpperBoundDualStart <: AbstractAttribute end """ - VariableLowerBound(i) + VariableLowerBound -Lower-bound constraint on variable index `i`. `-Inf` is valid as no bound. +Lower-bound constraints on variables. `-Inf` is valid as no bound. """ -struct VariableLowerBound <: AbstractAttribute - i::Int -end +struct VariableLowerBound <: AbstractAttribute end + """ - VariableLowerBoundVector + VariableUpperBound -Lower-bound constraint vector for the variables. `-Inf` is valid as no bound. +Upper-bound constraints for the variables. `Inf` is valid as no bound. """ -struct VariableLowerBoundVector <: AbstractAttribute end +struct VariableUpperBound <: AbstractAttribute end """ - VariableUpperBound(i) + VariablePrimal(N) -Upper-bound constraint vector for the variables. `Inf` is valid as no bound. +The assignment to the primal variables in result `N`. If `N` is omitted, it is interpreted as 1. """ -struct VariableUpperBound <: AbstractAttribute - i::Int +struct VariablePrimal <: AbstractAttribute + N::Int end """ - VariableUpperBoundVector + VariableLowerBoundDual(N) -Upper-bound constraints on variable index `i`. `Inf` is valid as no bound. +The assignment to the duals on the variable lower bounds in result `N`. If `N` is omitted, it is interpreted as 1. """ -struct VariableUpperBoundVector <: AbstractAttribute end - +struct VariableLowerBoundDual <: AbstractAttribute + N::Int +end """ - VariableResult + VariableUpperBoundDual(N) -The assignment to the primal variables in result `N`. If `N` is omitted, it is interpreted as 1. +The assignment to the duals on the variable upper bounds in result `N`. If `N` is omitted, it is interpreted as 1. """ -struct VariableResult <: AbstractAttribute +struct VariableUpperBoundDual <: AbstractAttribute N::Int end + + # VarType? diff --git a/src/SolverInterface/constraints.jl b/src/SolverInterface/constraints.jl new file mode 100644 index 0000000..198b32f --- /dev/null +++ b/src/SolverInterface/constraints.jl @@ -0,0 +1,72 @@ + + +""" + ConstraintReference{T} + +A lightweight object used to reference constraints in a model. +The parameter `T` is the type of set constraint referenced. +""" +struct ConstraintReference{T} + value::UInt64 +end + +""" + candelete(m::AbstractMathProgModel, ref::ConstraintReference)::Bool + +Return a `Bool` indicating whether this constraint can be removed from the model `m`. +""" +candelete(m::AbstractMathProgModel, ref::ConstraintReference) = throw(MethodError()) + +""" + isalive(m::AbstractMathProgModel, ref::ConstraintReference)::Bool + +Return a `Bool` indicating whether this reference is valid +for an active constraint in the model `m`. +""" +isactive(m::AbstractMathProgModel, ref::ConstraintReference) = throw(MethodError()) + +""" + delete!(m::AbstractMathProgModel, ref::ConstraintReference) + +Delete the referenced variable from the model. +""" +Base.delete!(m::AbstractMathProgModel, ref::ConstraintReference) = throw(MethodError()) + + +""" + addconstraint!(m::AbstractMathProgModel, b, a_constridx, a_varidx, a_coef, Q_constridx, Q_vari, Q_varj, Q_coef, S::AbstractSet)::ConstraintReference{typeof(S)} + +Add the constraint +```math +Ax + b + q(x) \\in S +``` +where ``A`` is a sparse vector specified in triplet form by +`a_constridx`, `a_varidx`, and `a_coef`; ``b`` is a vector; +``q(x)`` is a vector with component ``(q(x))_k`` defined to be ``\\frac{1}{2}x^TQ_kx`` +where the symmetric matrix ``Q_k`` is defined by the triplets in `Q_vari`, `Q_varj`, +`Q_coef` for which `Q_constridx` equals `k`; and the set ``S`` is defined by `S`. + +Duplicate indices in either ``A`` or a ``Q`` matrix are accepted and will be summed together. Off-diagonal entries of ``Q`` will be mirrored, so either the upper triangular or lower triangular entries of ``Q`` should be provided. If entries for both ``(i,j)`` and ``(j,i)`` are provided, these are considered duplicate terms. `a_varidx`, `Q_vari`, `Q_varj` should be collections of `VariableReference` objects. + + addconstraint!(m::AbstractMathProgModel, b, a_varidx, a_coef, Q_vari, Q_varj, Q_coef, S::AbstractSet)::ConstraintReference{typeof(S)} + +A specialized version of `addconstraint!` for one-dimensional sets. +Add the constraint +```math +a^Tx + b + \\frac{1}{2}x^TQx \\in S +``` +where ``a`` is a sparse vector specified in tuple form by +`a_varidx`, and `a_coef`; ``b`` is a scalar; +the symmetric matrix ``Q`` is defined by the triplets in `Q_vari`, `Q_varj`, +`Q_coef`; and the set ``S`` is defined by `S`. + + addconstraint!(m::AbstractMathProgModel, varidx, S::AbstractSet)::ConstraintReference{typeof(S)} + +A specialized version of `addconstraint!` for constraints on subsets of variables. +Add the constraint +```math +x_{varidx} \\in S +``` +where `varidx` specifies the indices of the subvector of `x`. +""" +function addconstraint! end diff --git a/src/SolverInterface/sets.jl b/src/SolverInterface/sets.jl index d3996a8..6d97696 100644 --- a/src/SolverInterface/sets.jl +++ b/src/SolverInterface/sets.jl @@ -69,40 +69,3 @@ end dimension(s::Union{NonNegative,NonPositive,Zero,Integers,Binaries}) = s.dim -""" - addconstraint!(m::AbstractMathProgModel, b, a_constridx, a_varidx, a_coef, Q_constridx, Q_vari, Q_varj, Q_coef, S::AbstractSet) - -Add the constraint -```math -Ax + b + q(x) \\in S -``` -where ``A`` is a sparse vector specified in triplet form by -`a_constridx`, `a_varidx`, and `a_coef`; ``b`` is a vector; -``q(x)`` is a vector with component ``(q(x))_k`` defined to be ``\\frac{1}{2}x^TQ_kx`` -where the symmetric matrix ``Q_k`` is defined by the triplets in `Q_vari`, `Q_varj`, -`Q_coef` for which `Q_constridx` equals `k`; and the set ``S`` is defined by `S`. - -Duplicate indices in either ``A`` or a ``Q`` matrix are accepted and will be summed together. Off-diagonal entries of ``Q`` will be mirrored, so either the upper triangular or lower triangular entries of ``Q`` should be provided. If entries for both ``(i,j)`` and ``(j,i)`` are provided, these are considered duplicate terms. - - addconstraint!(m::AbstractMathProgModel, b, a_varidx, a_coef, Q_vari, Q_varj, Q_coef, S::AbstractSet) - -A specialized version of `addconstraint!` for one-dimensional sets. -Add the constraint -```math -a^Tx + b + \\frac{1}{2}x^TQx \\in S -``` -where ``a`` is a sparse vector specified in tuple form by -`a_varidx`, and `a_coef`; ``b`` is a scalar; -the symmetric matrix ``Q`` is defined by the triplets in `Q_vari`, `Q_varj`, -`Q_coef`; and the set ``S`` is defined by `S`. - - addconstraint!(m::AbstractMathProgModel, varidx, S::AbstractSet) - -A specialized version of `addconstraint!` for constraints on subsets of variables. -Add the constraint -```math -x_{varidx} \\in S -``` -where `varidx` specifies the indices of the subvector of `x`. -""" -function addconstraint! end diff --git a/src/SolverInterface/variables.jl b/src/SolverInterface/variables.jl new file mode 100644 index 0000000..98abd63 --- /dev/null +++ b/src/SolverInterface/variables.jl @@ -0,0 +1,48 @@ + +""" + VariableReference + +A lightweight object used to reference variables in a model. +""" +struct VariableReference + value::UInt64 +end + +""" + candelete(m::AbstractMathProgModel,ref::VariableReference)::Bool + +Return a `Bool` indicating whether this variable can be removed from the model `m`. +""" +candelete(m::AbstractMathProgModel,ref::VariableReference) = throw(MethodError()) + +""" + isalive(m::AbstractMathProgModel, ref::VariableReference)::Bool + +Return a `Bool` indicating whether this reference is valid +for an active variable in the model `m`. +""" +isactive(m::AbstractMathProgModel, ref::VariableReference) = throw(MethodError()) + +""" + delete!(m::AbstractMathProgModel, ref::VariableReference) + +Delete the referenced variable from the model. +""" +Base.delete!(m::AbstractMathProgModel, ref::VariableReference) = throw(MethodError()) + + +""" + addvariables!(m::AbstractMathProgModel, N::Int) + +Add `N` scalar variables to the model, returning a vector of variable +references. +""" +function addvariables! end + +""" + addvariable!(m::AbstractMathProgModel, N::Int) + +Add a scalar variable to the model, returning a vector of variable +references. +""" +function addvariable! end From 5bfd73f3694ae7af4e8dd230689ac64f5056cd45 Mon Sep 17 00:00:00 2001 From: jac0320 Date: Wed, 14 Jun 2017 17:37:05 -0400 Subject: [PATCH 11/83] Minor fix for latex support --- docs/make.jl | 2 +- docs/mkdoc.yml | 9 --------- 2 files changed, 1 insertion(+), 10 deletions(-) delete mode 100644 docs/mkdoc.yml diff --git a/docs/make.jl b/docs/make.jl index 009c642..0c6dc59 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -18,6 +18,6 @@ deploydocs( target = "build", osname = "linux", julia = "0.6", - deps = Deps.pip("pygments", "mkdocs", "python-markdown-math"), + deps = nothing, make = nothing ) diff --git a/docs/mkdoc.yml b/docs/mkdoc.yml deleted file mode 100644 index 4585041..0000000 --- a/docs/mkdoc.yml +++ /dev/null @@ -1,9 +0,0 @@ -# ... -markdown_extensions: - - mdx_math - # ... - -extra_javascript: - - https://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS_HTML - - assets/mathjaxhelper.js -# ... From 1e5a9b29a42eda008cb9c3e051122cc8ac0055b5 Mon Sep 17 00:00:00 2001 From: Miles Lubin Date: Wed, 14 Jun 2017 17:43:49 -0400 Subject: [PATCH 12/83] isactive -> isvalid --- docs/src/solverinterface.md | 4 ++-- src/SolverInterface/constraints.jl | 4 ++-- src/SolverInterface/variables.jl | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/src/solverinterface.md b/docs/src/solverinterface.md index fe609d0..3fc4b31 100644 --- a/docs/src/solverinterface.md +++ b/docs/src/solverinterface.md @@ -21,7 +21,7 @@ freemodel! ```@docs VariableReference candelete(::AbstractMathProgModel,::VariableReference) -isactive(::AbstractMathProgModel,::VariableReference) +isvalid(::AbstractMathProgModel,::VariableReference) delete!(::AbstractMathProgModel,::VariableReference) addvariables! addvariable! @@ -33,7 +33,7 @@ How to add constraints. ```@docs ConstraintReference candelete(::AbstractMathProgModel,::ConstraintReference) -isactive(::AbstractMathProgModel,::ConstraintReference) +isvalid(::AbstractMathProgModel,::ConstraintReference) delete!(::AbstractMathProgModel,::ConstraintReference) addconstraint! ``` diff --git a/src/SolverInterface/constraints.jl b/src/SolverInterface/constraints.jl index 198b32f..0651563 100644 --- a/src/SolverInterface/constraints.jl +++ b/src/SolverInterface/constraints.jl @@ -18,12 +18,12 @@ Return a `Bool` indicating whether this constraint can be removed from the model candelete(m::AbstractMathProgModel, ref::ConstraintReference) = throw(MethodError()) """ - isalive(m::AbstractMathProgModel, ref::ConstraintReference)::Bool + isvalid(m::AbstractMathProgModel, ref::ConstraintReference)::Bool Return a `Bool` indicating whether this reference is valid for an active constraint in the model `m`. """ -isactive(m::AbstractMathProgModel, ref::ConstraintReference) = throw(MethodError()) +isvalid(m::AbstractMathProgModel, ref::ConstraintReference) = throw(MethodError()) """ delete!(m::AbstractMathProgModel, ref::ConstraintReference) diff --git a/src/SolverInterface/variables.jl b/src/SolverInterface/variables.jl index 98abd63..2eade76 100644 --- a/src/SolverInterface/variables.jl +++ b/src/SolverInterface/variables.jl @@ -16,12 +16,12 @@ Return a `Bool` indicating whether this variable can be removed from the model ` candelete(m::AbstractMathProgModel,ref::VariableReference) = throw(MethodError()) """ - isalive(m::AbstractMathProgModel, ref::VariableReference)::Bool + isvalid(m::AbstractMathProgModel, ref::VariableReference)::Bool Return a `Bool` indicating whether this reference is valid for an active variable in the model `m`. """ -isactive(m::AbstractMathProgModel, ref::VariableReference) = throw(MethodError()) +isvalid(m::AbstractMathProgModel, ref::VariableReference) = throw(MethodError()) """ delete!(m::AbstractMathProgModel, ref::VariableReference) From 9c005e469d8eadca11b082d854181848fe912778 Mon Sep 17 00:00:00 2001 From: Miles Lubin Date: Wed, 14 Jun 2017 17:44:47 -0400 Subject: [PATCH 13/83] typo --- src/SolverInterface/attributes.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/SolverInterface/attributes.jl b/src/SolverInterface/attributes.jl index a28435b..dfe99d4 100644 --- a/src/SolverInterface/attributes.jl +++ b/src/SolverInterface/attributes.jl @@ -26,7 +26,7 @@ function getattribute end """ getattribute!(output, m::AbstractMathProgModel, attr::AbstractAttribute) -An in-place version of `getattribute!`. Return an attribute of the model `m` specified by attribute type `attr` into output vector `attr`. +An in-place version of `getattribute`. Return an attribute of the model `m` specified by attribute type `attr` into output vector `attr`. """ function getattribute! end From 60638074a54a524ce0a1bc79bfdd380c0f516256 Mon Sep 17 00:00:00 2001 From: Miles Lubin Date: Wed, 14 Jun 2017 17:45:01 -0400 Subject: [PATCH 14/83] todo is done --- src/SolverInterface/attributes.jl | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/SolverInterface/attributes.jl b/src/SolverInterface/attributes.jl index dfe99d4..a58c172 100644 --- a/src/SolverInterface/attributes.jl +++ b/src/SolverInterface/attributes.jl @@ -6,9 +6,6 @@ to set or get attributes (properties) of the model. """ abstract type AbstractAttribute end -# TODO: -# in-place getters - """ getattribute(m::AbstractMathProgModel, attr::AbstractAttribute) From d607a861767d26f6cefbb2861971b7910b848c66 Mon Sep 17 00:00:00 2001 From: jac0320 Date: Wed, 14 Jun 2017 17:45:11 -0400 Subject: [PATCH 15/83] Resolve conflicts with SolverInterFace.md --- docs/src/solverinterface.md | 24 +----------------------- 1 file changed, 1 insertion(+), 23 deletions(-) diff --git a/docs/src/solverinterface.md b/docs/src/solverinterface.md index 1bb5bae..fba1b37 100644 --- a/docs/src/solverinterface.md +++ b/docs/src/solverinterface.md @@ -16,23 +16,6 @@ optimize! freemodel! ``` -## Sets - -How to add constraints. -```@docs -addconstraint! -``` - -List of sets. -```@docs -NonNegative -NonPositive -Zero -Interval -Integers -Binaries -``` - ## Attributes These are used to get and set properties of the model. @@ -64,12 +47,7 @@ ResultCount ```@docs VariableStart -VariableLowerBoundDualStart -VariableUpperBoundDualStart -VariableLowerBound -VariableLowerBoundVector -VariableUpperBound -VariableUpperBoundVector +VariableDualStart VariableResult ``` From 3ab0181889e7787fab713cc599ce1368c2817f20 Mon Sep 17 00:00:00 2001 From: Miles Lubin Date: Wed, 14 Jun 2017 17:51:41 -0400 Subject: [PATCH 16/83] replace sense symbol with enum --- src/SolverInterface/attributes.jl | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/SolverInterface/attributes.jl b/src/SolverInterface/attributes.jl index a58c172..be3f46c 100644 --- a/src/SolverInterface/attributes.jl +++ b/src/SolverInterface/attributes.jl @@ -84,10 +84,12 @@ struct SolveTime <: AbstractAttribute end """ Sense -The optimization sense of the model. Valid values are `:Min` and `:Max`. +The optimization sense of the model, an `OptimizationSense` with value `MinSense` or `MaxSense`. """ struct Sense <: AbstractAttribute end +@enum OptimizationSense MinSense MaxSense + """ SimplexIterations From ff15c3d6809b3ca0ede898c5cd3ffefd896b34c8 Mon Sep 17 00:00:00 2001 From: Miles Lubin Date: Wed, 14 Jun 2017 17:56:22 -0400 Subject: [PATCH 17/83] dimension of interval --- src/SolverInterface/sets.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/SolverInterface/sets.jl b/src/SolverInterface/sets.jl index 6d97696..fa1b778 100644 --- a/src/SolverInterface/sets.jl +++ b/src/SolverInterface/sets.jl @@ -46,7 +46,7 @@ struct Interval{T} <: AbstractSet upper::T end -dimension(s::Interval) = 1 +dimension(s::Interval) = length(s.lower) """ Integers(n) From 8c08031c48c9bf802e64cd788dd03bfc77d520e2 Mon Sep 17 00:00:00 2001 From: Miles Lubin Date: Wed, 14 Jun 2017 18:16:35 -0400 Subject: [PATCH 18/83] discussion of duals --- docs/src/solverinterface.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/src/solverinterface.md b/docs/src/solverinterface.md index b2fa94c..b023b76 100644 --- a/docs/src/solverinterface.md +++ b/docs/src/solverinterface.md @@ -101,3 +101,7 @@ The `TerminationStatus` attribute is meant to explain the reason why the solver ```@docs TerminationStatusCode ``` + +## Duals + +We take the convention that duals on variable lower bounds should be nonnegative, duals on variable upper bounds should be nonpositive, and duals on closed convex cones should belong to the dual cone. From 4f33981e0674cc44323539a8cea6f924694a75de Mon Sep 17 00:00:00 2001 From: Miles Lubin Date: Thu, 15 Jun 2017 08:57:33 -0400 Subject: [PATCH 19/83] constructor for VariablePrimal --- src/SolverInterface/attributes.jl | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/SolverInterface/attributes.jl b/src/SolverInterface/attributes.jl index 72abefb..f94738a 100644 --- a/src/SolverInterface/attributes.jl +++ b/src/SolverInterface/attributes.jl @@ -170,12 +170,14 @@ struct VariableUpperBound <: AbstractAttribute end """ VariablePrimal(N) + VariablePrimal() -The assignment to the primal variables in result `N`. If `N` is omitted, it is interpreted as 1. +The assignment to the primal variables in result `N`. If `N` is omitted, it is 1 by default. """ struct VariablePrimal <: AbstractAttribute N::Int end +VariablePrimal() = VariablePrimal(1) """ VariableLowerBoundDual(N) From efad7dbcfc8893f3a9a517fbeb1fd2545b6b098d Mon Sep 17 00:00:00 2001 From: Miles Lubin Date: Thu, 15 Jun 2017 09:22:21 -0400 Subject: [PATCH 20/83] document result status --- docs/src/solverinterface.md | 15 +++++++- src/SolverInterface/attributes.jl | 61 +++++++++++++++++++++++++++---- 2 files changed, 68 insertions(+), 8 deletions(-) diff --git a/docs/src/solverinterface.md b/docs/src/solverinterface.md index b023b76..47205ad 100644 --- a/docs/src/solverinterface.md +++ b/docs/src/solverinterface.md @@ -80,7 +80,7 @@ ResultCount ### Variable Attributes -These attributes are associated with variables. Calls to `getattribute` and `setattribute!` should include a single `VariableReference` or a vector of `VariableReference` objects. +These attributes are associated with variables. Calls to `getattribute` and `setattribute!` should include as an argument a single `VariableReference` or a vector of `VariableReference` objects. ```@docs VariableStart @@ -99,9 +99,22 @@ VariableUpperBoundDual The `TerminationStatus` attribute is meant to explain the reason why the solver stopped executing. The value of the attribute is of type `TerminationStatusCode`. ```@docs +TerminationStatus TerminationStatusCode ``` +## Result Status + +The `PrimalStatus` and `DualStatus` attributes are meant to explain how to interpret the result returned by the solver. The value of the attributes are of type `ResultStatus`. + +```@docs +PrimalStatus +DualStatus +ResultStatus +``` + + ## Duals We take the convention that duals on variable lower bounds should be nonnegative, duals on variable upper bounds should be nonpositive, and duals on closed convex cones should belong to the dual cone. + diff --git a/src/SolverInterface/attributes.jl b/src/SolverInterface/attributes.jl index f94738a..6c72499 100644 --- a/src/SolverInterface/attributes.jl +++ b/src/SolverInterface/attributes.jl @@ -52,11 +52,15 @@ function setattribute! end # Scalar attributes """ - ObjectiveValue + ObjectiveValue(N) + ObjectiveValue() -The objective value of the best primal result vector found by the solver. +The objective value of the primal result `N`. If `N` is omitted, it defaults to 1. """ -struct ObjectiveValue <: AbstractAttribute end +struct ObjectiveValue <: AbstractAttribute + N::Int +end +ObjectiveValue() = ObjectiveValue(1) """ ObjectiveBound @@ -126,6 +130,8 @@ The number of results available. struct ResultCount <: AbstractAttribute end + + # Variable attributes """ @@ -203,17 +209,17 @@ end function getsolution end -function getobjval end -function setvartype! end -function getvartype end function loadproblem! end -function setwarmstart! end # Termination status +""" + TerminationStatus +A `TerminationStatusCode` explaining why the solver stopped. +""" struct TerminationStatus <: AbstractAttribute end """ @@ -250,3 +256,44 @@ To be documented: `NumericalError`, `InvalidModel`, `InvalidOption`, `Interrupte """ @enum TerminationStatusCode Success AlmostSuccess InfeasibleNoResult UnboundedNoResult InfeasibleOrUnbounded IterationLimit TimeLimit NodeLimit SolutionLimit MemoryLimit ObjectiveLimit NormLimit OtherLimit SlowProgress NumericalError InvalidModel InvalidOption Interrupted OtherError + +# Result status + +""" + ResultStatus + +An Enum of possible values for the `PrimalStatus` and `DualStatus` attributes. The values indicate how to interpret the result vector. + + * `FeasiblePoint` + * `NearlyFeasiblePoint` + * `InfeasiblePoint` + * `InfeasibilityCertificate` + * `NearlyInfeasibilityCertificate` + * `ReductionCertificate` + * `NearlyReductionCertificate` + * `Unknown` + * `Other` +""" +@enum ResultStatus FeasiblePoint NearlyFeasiblePoint InfeasiblePoint InfeasibilityCertificate NearlyInfeasibilityCertificate ReductionCertificate NearlyReductionCertificate Unknown Other + +""" + PrimalStatus(N) + PrimalStatus() + +The `ResultStatus` of the primal result `N`. If `N` is omitted, it defaults to 1. +""" +struct PrimalStatus <: AbstractAttribute + N::Int +end +PrimalStatus() = PrimalStatus(1) + +""" + DualStatus(N) + DualStatus() + +The `ResultStatus` of the dual result `N`. If `N` is omitted, it defaults to 1. +""" +struct DualStatus <: AbstractAttribute + N::Int +end +DualStatus() = DualStatus(1) From 2f3320b80b12f1a34802b3955c14b8de88f7d1cf Mon Sep 17 00:00:00 2001 From: Joey Huchette Date: Thu, 15 Jun 2017 09:28:24 -0400 Subject: [PATCH 21/83] Constructors for VariableLower/UpperBoundDual --- src/SolverInterface/attributes.jl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/SolverInterface/attributes.jl b/src/SolverInterface/attributes.jl index 6c72499..edb45e4 100644 --- a/src/SolverInterface/attributes.jl +++ b/src/SolverInterface/attributes.jl @@ -193,6 +193,7 @@ The assignment to the duals on the variable lower bounds in result `N`. If `N` i struct VariableLowerBoundDual <: AbstractAttribute N::Int end +VariableLowerBoundDual() = VariableLowerBoundDual(1) """ VariableUpperBoundDual(N) @@ -202,7 +203,7 @@ The assignment to the duals on the variable upper bounds in result `N`. If `N` i struct VariableUpperBoundDual <: AbstractAttribute N::Int end - +VariableUpperBoundDual() = VariableUpperBoundDual(1) # VarType? From fab357ea317324b1de48129eefca1894d6f76c31 Mon Sep 17 00:00:00 2001 From: Miles Lubin Date: Thu, 15 Jun 2017 09:33:06 -0400 Subject: [PATCH 22/83] [ci skip] tidy --- docs/src/solverinterface.md | 2 +- src/SolverInterface/attributes.jl | 42 +++++++++++++++---------------- 2 files changed, 21 insertions(+), 23 deletions(-) diff --git a/docs/src/solverinterface.md b/docs/src/solverinterface.md index 47205ad..a3ce772 100644 --- a/docs/src/solverinterface.md +++ b/docs/src/solverinterface.md @@ -105,7 +105,7 @@ TerminationStatusCode ## Result Status -The `PrimalStatus` and `DualStatus` attributes are meant to explain how to interpret the result returned by the solver. The value of the attributes are of type `ResultStatus`. +The `PrimalStatus` and `DualStatus` attributes are meant to explain how to interpret the result returned by the solver. The value of the attributes are of type `ResultStatusCode`. ```@docs PrimalStatus diff --git a/src/SolverInterface/attributes.jl b/src/SolverInterface/attributes.jl index 6c72499..9e25165 100644 --- a/src/SolverInterface/attributes.jl +++ b/src/SolverInterface/attributes.jl @@ -63,30 +63,28 @@ end ObjectiveValue() = ObjectiveValue(1) """ - ObjectiveBound + ObjectiveBound() The best known bound on the optimal objective value. """ struct ObjectiveBound <: AbstractAttribute end - -struct RelativeGapAttr <: AbstractAttribute end """ - RelativeGap + RelativeGap() The final relative optimality gap as optimization terminated. That is, ``\\frac{|b-f|}{|f|}``, where ``b`` is the best bound and ``f`` is the best feasible objective value. """ -const RelativeGap = RelativeGapAttr() +struct RelativeGap <: AbstractAttribute end """ - SolveTime + SolveTime() The total elapsed solution time (in seconds) as reported by the solver. """ struct SolveTime <: AbstractAttribute end """ - Sense + Sense() The optimization sense of the model, an `OptimizationSense` with value `MinSense` or `MaxSense`. """ @@ -95,35 +93,35 @@ struct Sense <: AbstractAttribute end @enum OptimizationSense MinSense MaxSense """ - SimplexIterations + SimplexIterations() The cumulative number of simplex iterations during the optimization process. In particular, for a MIP the total simplex iterations for all nodes. """ struct SimplexIterations <: AbstractAttribute end """ - BarrierIterations + BarrierIterations() The cumulative number of barrier iterations during the optimization process. """ struct BarrierIterations <: AbstractAttribute end """ - NodeCount + NodeCount() The total number of branch-and-bound nodes explored. """ struct NodeCount <: AbstractAttribute end """ - RawSolver + RawSolver() An object that may be used to access a solver-specific API for this model. """ struct RawSolver <: AbstractAttribute end """ - ResultCount + ResultCount() The number of results available. """ @@ -135,7 +133,7 @@ struct ResultCount <: AbstractAttribute end # Variable attributes """ - VariableStart + VariableStart() An initial assignment of the variables that the solver may use to warm-start the solve. @@ -143,7 +141,7 @@ to warm-start the solve. struct VariableStart <: AbstractAttribute end """ - VariableLowerBoundDualStart + VariableLowerBoundDualStart() An initial assignment of the variable lower-bound duals that the solver may use to warm-start the solve. @@ -151,7 +149,7 @@ to warm-start the solve. struct VariableLowerBoundDualStart <: AbstractAttribute end """ - VariableUpperBoundDualStart + VariableUpperBoundDualStart() An initial assignment of the variable upper-bound duals that the solver may use to warm-start the solve. @@ -160,7 +158,7 @@ struct VariableUpperBoundDualStart <: AbstractAttribute end """ - VariableLowerBound + VariableLowerBound() Lower-bound constraints on variables. `-Inf` is valid as no bound. """ @@ -168,7 +166,7 @@ struct VariableLowerBound <: AbstractAttribute end """ - VariableUpperBound + VariableUpperBound() Upper-bound constraints for the variables. `Inf` is valid as no bound. """ @@ -216,7 +214,7 @@ function loadproblem! end # Termination status """ - TerminationStatus + TerminationStatus() A `TerminationStatusCode` explaining why the solver stopped. """ @@ -260,7 +258,7 @@ To be documented: `NumericalError`, `InvalidModel`, `InvalidOption`, `Interrupte # Result status """ - ResultStatus + ResultStatusCode An Enum of possible values for the `PrimalStatus` and `DualStatus` attributes. The values indicate how to interpret the result vector. @@ -274,13 +272,13 @@ An Enum of possible values for the `PrimalStatus` and `DualStatus` attributes. T * `Unknown` * `Other` """ -@enum ResultStatus FeasiblePoint NearlyFeasiblePoint InfeasiblePoint InfeasibilityCertificate NearlyInfeasibilityCertificate ReductionCertificate NearlyReductionCertificate Unknown Other +@enum ResultStatusCode FeasiblePoint NearlyFeasiblePoint InfeasiblePoint InfeasibilityCertificate NearlyInfeasibilityCertificate ReductionCertificate NearlyReductionCertificate Unknown Other """ PrimalStatus(N) PrimalStatus() -The `ResultStatus` of the primal result `N`. If `N` is omitted, it defaults to 1. +The `ResultStatusCode` of the primal result `N`. If `N` is omitted, it defaults to 1. """ struct PrimalStatus <: AbstractAttribute N::Int @@ -291,7 +289,7 @@ PrimalStatus() = PrimalStatus(1) DualStatus(N) DualStatus() -The `ResultStatus` of the dual result `N`. If `N` is omitted, it defaults to 1. +The `ResultStatusCode` of the dual result `N`. If `N` is omitted, it defaults to 1. """ struct DualStatus <: AbstractAttribute N::Int From 0e69f4a20cc5d63f81423b94de84f2962dcc0e78 Mon Sep 17 00:00:00 2001 From: Miles Lubin Date: Thu, 15 Jun 2017 09:35:13 -0400 Subject: [PATCH 23/83] [ci skip] fix reference in docs, add todo --- docs/src/solverinterface.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/docs/src/solverinterface.md b/docs/src/solverinterface.md index a3ce772..7b519a0 100644 --- a/docs/src/solverinterface.md +++ b/docs/src/solverinterface.md @@ -110,9 +110,13 @@ The `PrimalStatus` and `DualStatus` attributes are meant to explain how to inter ```@docs PrimalStatus DualStatus -ResultStatus +ResultStatusCode ``` +## Basis Status + +TODO: attributes and status codes for LP basis status + ## Duals From b77bfd70bcc95f3d28e54a2348494cb3a2adb3e8 Mon Sep 17 00:00:00 2001 From: Miles Lubin Date: Thu, 15 Jun 2017 09:55:57 -0400 Subject: [PATCH 24/83] [ci skip] constraint attributes --- docs/src/solverinterface.md | 14 ++++++++++- src/SolverInterface/attributes.jl | 42 +++++++++++++++++++++++++++---- 2 files changed, 50 insertions(+), 6 deletions(-) diff --git a/docs/src/solverinterface.md b/docs/src/solverinterface.md index 7b519a0..3ba8a9a 100644 --- a/docs/src/solverinterface.md +++ b/docs/src/solverinterface.md @@ -83,7 +83,7 @@ ResultCount These attributes are associated with variables. Calls to `getattribute` and `setattribute!` should include as an argument a single `VariableReference` or a vector of `VariableReference` objects. ```@docs -VariableStart +VariablePrimalStart VariableLowerBoundDualStart VariableUpperBoundDualStart VariableLowerBound @@ -93,6 +93,18 @@ VariableLowerBoundDual VariableUpperBoundDual ``` +### Constraint Attributes + +These attributes are associated with constraints. Calls to `getattribute` and `setattribute!` should include as an argument a single `ConstraintReference` or a vector of `ConstriaintReference{T}` objects. + +```@docs +ConstraintPrimalStart +ConstraintDualStart +ConstraintPrimal +ConstraintDual +``` + + ## Termination Status diff --git a/src/SolverInterface/attributes.jl b/src/SolverInterface/attributes.jl index c25c156..bc0b002 100644 --- a/src/SolverInterface/attributes.jl +++ b/src/SolverInterface/attributes.jl @@ -133,12 +133,12 @@ struct ResultCount <: AbstractAttribute end # Variable attributes """ - VariableStart() + VariablePrimalStart() An initial assignment of the variables that the solver may use to warm-start the solve. """ -struct VariableStart <: AbstractAttribute end +struct VariablePrimalStart <: AbstractAttribute end """ VariableLowerBoundDualStart() @@ -204,13 +204,45 @@ end VariableUpperBoundDual() = VariableUpperBoundDual(1) -# VarType? +# Constraint attributes +""" + ConstraintPrimalStart() + +An initial assignment of the constraint primal values that the solver may use +to warm-start the solve. +""" +struct ConstraintPrimalStart <: AbstractAttribute end + +""" + ConstraintDualStart() + +An initial assignment of the constriant duals that the solver may use +to warm-start the solve. +""" +struct ConstraintDualStart <: AbstractAttribute end -function getsolution end +""" + ConstraintPrimal(N) + ConstraintPrimal() +The assignment to the constraint primal values in result `N`. If `N` is omitted, it is 1 by default. +""" +struct ConstraintPrimal <: AbstractAttribute + N::Int +end +ConstraintPrimal() = ConstraintPrimal(1) -function loadproblem! end +""" + ConstraintDual(N) + ConstraintDual() + +The assignment to the constraint dual values in result `N`. If `N` is omitted, it is 1 by default. +""" +struct ConstraintDual <: AbstractAttribute + N::Int +end +ConstraintDual() = ConstraintDual(1) # Termination status From b814ac704d509b3d967c4320ea9f06323deec676 Mon Sep 17 00:00:00 2001 From: Joey Huchette Date: Thu, 15 Jun 2017 10:04:25 -0400 Subject: [PATCH 25/83] Add SOS constraints --- src/SolverInterface/constraints.jl | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/SolverInterface/constraints.jl b/src/SolverInterface/constraints.jl index 0651563..66fc9d9 100644 --- a/src/SolverInterface/constraints.jl +++ b/src/SolverInterface/constraints.jl @@ -70,3 +70,17 @@ x_{varidx} \\in S where `varidx` specifies the indices of the subvector of `x`. """ function addconstraint! end + +""" + addsos1!(m::AbstractMathProgModel, idx, weight) + +Adds a special ordered set (SOS) constraint of type 1. Of the variables indexed by ``idx``, at most one can be nonzero. The ``weight`` argument induces the ordering of the variables; as such, they should be unique values. A typical SOS1 constraint might look like ``y=\\sum_i w_i x_i``, where ``x_i \\in \\{0,1\\}`` are binary variables and the ``w_i`` are weights. See [here](http://lpsolve.sourceforge.net/5.5/SOS.htm) for a description of SOS constraints and their potential uses. +""" +function addsos1! end + +""" + addsos2!(m::AbstractMathProgModel, idx, weight) + +Adds a special ordered set (SOS) constraint of type 2. Of the variables indexed by ``idx``, at most two can be nonzero, and if two are nonzero, they must be adjacent in the set. The ``weight`` argument induces the ordering of the variables; as such, they should be unique values. A common application for SOS2 constraints is modeling nonconvex piecewise linear functions; see [here](http://lpsolve.sourceforge.net/5.5/SOS.htm) for details. +""" +function addsos2! end From 3b32653a62c522543012dbf1a8bec8643ae3e1e5 Mon Sep 17 00:00:00 2001 From: Joey Huchette Date: Thu, 15 Jun 2017 10:20:46 -0400 Subject: [PATCH 26/83] Fallback methods for attribute getters/setters --- src/SolverInterface/attributes.jl | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/SolverInterface/attributes.jl b/src/SolverInterface/attributes.jl index bc0b002..e3f9cc1 100644 --- a/src/SolverInterface/attributes.jl +++ b/src/SolverInterface/attributes.jl @@ -7,7 +7,7 @@ to set or get attributes (properties) of the model. abstract type AbstractAttribute end """ - getattribute(m::AbstractMathProgModel, attr::AbstractAttribute) + getattribute(m::AbstractMathProgModel, attr::AbstractAttribute, extra_args...) Return an attribute of the model `m` specified by attribute type `attr`. @@ -20,12 +20,19 @@ Return an attribute of the model `m` specified by attribute type `attr`. """ function getattribute end +function getattribute(m, attr::AbstractAttribute, args...) + throw(ArgumentError("Model of type $(typeof(m)) does not support accessing the attribute $attr")) +end + """ - getattribute!(output, m::AbstractMathProgModel, attr::AbstractAttribute) + getattribute!(output, m::AbstractMathProgModel, attr::AbstractAttribute, extra_args...) An in-place version of `getattribute`. Return an attribute of the model `m` specified by attribute type `attr` into output vector `attr`. """ function getattribute! end +function getattribute!(output, m, attr::AbstractAttribute, args...) + throw(ArgumentError("Model of type $(typeof(m)) does not support accessing the attribute $attr")) +end """ cangetattribute(m::AbstractMathProgModel, attr::AbstractAttribute)::Bool @@ -34,6 +41,7 @@ Return a `Bool` indicating whether the model `m` currently has a value for the attributed specified by attribute type `attr`. """ function cangetattribute end +cangetattribute(m::AbstractMathProgModel, attr::AbstractAttribute) = false """ cansetattribute(m::AbstractMathProgModel, attr::AbstractAttribute)::Bool @@ -42,6 +50,7 @@ Return a `Bool` indicating whether the model `m` will accept a `setattribute!` call for the attributed specified by attribute type `attr`. """ function cansetattribute end +cansetattribute(m::AbstractMathProgModel, attr::AbstractAttribute) = false """ setattribute!(m::AbstractMathProgModel, attr::AbstractAttribute, ...) @@ -49,6 +58,9 @@ function cansetattribute end Set an attribute of the model `m` specified by attribute type `attr`. """ function setattribute! end +function setattribute!(m, attr::AbstractAttribute, args...) + throw(ArgumentError("Model of type $(typeof(m)) does not support setting the attribute $attr")) +end # Scalar attributes """ From 845482163ce1ef169cce381af98b554805802b66 Mon Sep 17 00:00:00 2001 From: Joey Huchette Date: Thu, 15 Jun 2017 10:32:06 -0400 Subject: [PATCH 27/83] Move SOS to sets --- src/SolverInterface/constraints.jl | 14 -------------- src/SolverInterface/sets.jl | 25 ++++++++++++++++++++++++- 2 files changed, 24 insertions(+), 15 deletions(-) diff --git a/src/SolverInterface/constraints.jl b/src/SolverInterface/constraints.jl index 66fc9d9..0651563 100644 --- a/src/SolverInterface/constraints.jl +++ b/src/SolverInterface/constraints.jl @@ -70,17 +70,3 @@ x_{varidx} \\in S where `varidx` specifies the indices of the subvector of `x`. """ function addconstraint! end - -""" - addsos1!(m::AbstractMathProgModel, idx, weight) - -Adds a special ordered set (SOS) constraint of type 1. Of the variables indexed by ``idx``, at most one can be nonzero. The ``weight`` argument induces the ordering of the variables; as such, they should be unique values. A typical SOS1 constraint might look like ``y=\\sum_i w_i x_i``, where ``x_i \\in \\{0,1\\}`` are binary variables and the ``w_i`` are weights. See [here](http://lpsolve.sourceforge.net/5.5/SOS.htm) for a description of SOS constraints and their potential uses. -""" -function addsos1! end - -""" - addsos2!(m::AbstractMathProgModel, idx, weight) - -Adds a special ordered set (SOS) constraint of type 2. Of the variables indexed by ``idx``, at most two can be nonzero, and if two are nonzero, they must be adjacent in the set. The ``weight`` argument induces the ordering of the variables; as such, they should be unique values. A common application for SOS2 constraints is modeling nonconvex piecewise linear functions; see [here](http://lpsolve.sourceforge.net/5.5/SOS.htm) for details. -""" -function addsos2! end diff --git a/src/SolverInterface/sets.jl b/src/SolverInterface/sets.jl index fa1b778..b2d71d9 100644 --- a/src/SolverInterface/sets.jl +++ b/src/SolverInterface/sets.jl @@ -2,7 +2,7 @@ """ AbstractSet - + Abstract supertype for set objects used to encode constraints. """ abstract type AbstractSet end @@ -69,3 +69,26 @@ end dimension(s::Union{NonNegative,NonPositive,Zero,Integers,Binaries}) = s.dim +""" + SOS1(weights::Vector{T}) where T + +The set corresponding to the special ordered set (SOS) constraint of type 1. Of the variables in the set, at most one can be nonzero. The ``weights`` induce an ordering of the variables; as such, they should be unique values. The ``k``-th element in the set corresponds to the ``k``-th weight in ``weights``. + +See [here](http://lpsolve.sourceforge.net/5.5/SOS.htm) for a description of SOS constraints and their potential uses. +""" +struct SOS1{T} <: AbstractSet + weights::Vector{T} +end +dimension(s::SOS1) = length(s.weights) + +""" + SOS2(weights::Vector{T}) where T + +The set corresponding to the special ordered set (SOS) constraint of type 2. Of the variables in the set, at most two can be nonzero, and if two are nonzero, they must be adjacent in the ordering of the set. The ``weights`` induce an ordering of the variables; as such, they should be unique values. The ``k``-th element in the set corresponds to the ``k``-th weight in ``weights``. + +See [here](http://lpsolve.sourceforge.net/5.5/SOS.htm) for a description of SOS constraints and their potential uses. +""" +struct SOS2{T} <: AbstractSet + weights::Vector{T} +end +dimension(s::SOS2) = length(s.weights) From a79e635dd894df0b831d4a2234474c83a7eb2e00 Mon Sep 17 00:00:00 2001 From: joaquimgarcia_psr Date: Thu, 15 Jun 2017 11:35:51 -0300 Subject: [PATCH 28/83] Add the option for deleting multiple variables and constraints --- src/SolverInterface/constraints.jl | 7 ++++++- src/SolverInterface/variables.jl | 11 ++++++++--- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/src/SolverInterface/constraints.jl b/src/SolverInterface/constraints.jl index 0651563..7fdead8 100644 --- a/src/SolverInterface/constraints.jl +++ b/src/SolverInterface/constraints.jl @@ -28,9 +28,14 @@ isvalid(m::AbstractMathProgModel, ref::ConstraintReference) = throw(MethodError( """ delete!(m::AbstractMathProgModel, ref::ConstraintReference) -Delete the referenced variable from the model. +Delete the referenced constraint from the model. + + delete!(m::AbstractMathProgModel, refs::Vector{ConstraintReference}) + +Delete the referenced constraints in the vector `refs` from the model. """ Base.delete!(m::AbstractMathProgModel, ref::ConstraintReference) = throw(MethodError()) +Base.delete!(m::AbstractMathProgModel, refs::Vector{ConstraintReference}) = throw(MethodError()) """ diff --git a/src/SolverInterface/variables.jl b/src/SolverInterface/variables.jl index 2eade76..1891e8a 100644 --- a/src/SolverInterface/variables.jl +++ b/src/SolverInterface/variables.jl @@ -9,11 +9,11 @@ struct VariableReference end """ - candelete(m::AbstractMathProgModel,ref::VariableReference)::Bool + candelete(m::AbstractMathProgModel, ref::VariableReference)::Bool Return a `Bool` indicating whether this variable can be removed from the model `m`. """ -candelete(m::AbstractMathProgModel,ref::VariableReference) = throw(MethodError()) +candelete(m::AbstractMathProgModel, ref::VariableReference) = throw(MethodError()) """ isvalid(m::AbstractMathProgModel, ref::VariableReference)::Bool @@ -25,10 +25,15 @@ isvalid(m::AbstractMathProgModel, ref::VariableReference) = throw(MethodError()) """ delete!(m::AbstractMathProgModel, ref::VariableReference) - + Delete the referenced variable from the model. + + delete!(m::AbstractMathProgModel, refs::Vector{VariableReference}) + +Delete the referenced variables in the vector `refs` from the model. """ Base.delete!(m::AbstractMathProgModel, ref::VariableReference) = throw(MethodError()) +Base.delete!(m::AbstractMathProgModel, refs::Vector{VariableReference}) = throw(MethodError()) """ From 2de174f2982c45882a9cdac5218ceccd9ad7bf86 Mon Sep 17 00:00:00 2001 From: Miles Lubin Date: Thu, 15 Jun 2017 10:52:49 -0400 Subject: [PATCH 29/83] [ci skip] counts and supported sets --- docs/src/solverinterface.md | 5 ++++ src/SolverInterface/attributes.jl | 42 +++++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+) diff --git a/docs/src/solverinterface.md b/docs/src/solverinterface.md index 3ba8a9a..159fd75 100644 --- a/docs/src/solverinterface.md +++ b/docs/src/solverinterface.md @@ -76,6 +76,11 @@ BarrierIterations NodeCount RawSolver ResultCount +VariableCount +ConstraintCount +SupportsVariablesInSet +SupportsAffineInSet +SupportsQuadraticInSet ``` ### Variable Attributes diff --git a/src/SolverInterface/attributes.jl b/src/SolverInterface/attributes.jl index bc0b002..6306090 100644 --- a/src/SolverInterface/attributes.jl +++ b/src/SolverInterface/attributes.jl @@ -127,6 +127,48 @@ The number of results available. """ struct ResultCount <: AbstractAttribute end +""" + VariableCount() + +The number of variables in the model. +""" +struct VariableCount <: AbstractAttribute end + + +""" + ConstraintCount{T}() + +The number of constraints of type T in the model. +""" +struct ConstraintCount{T} <: AbstractAttribute end + +""" + SupportsVariablesInSet{T}() + +A `Bool` indicating whether the solver or model supports +a constraint of type ``x_{varidx} \\in S`` where ``S`` +is a set of type `T` and ``varidx`` indicates any subset +of the variables. +""" +struct SupportsVariablesInSet{T} <: AbstractAttribute end + +""" + SupportsAffineInSet{T}() + +A `Bool` indicating whether the solver or model supports +a constraint of of the form "affine expression" in ``S`` where ``S`` +is a set of type `T`. +""" +struct SupportsAffineInSet{T} <: AbstractAttribute end + +""" + SupportsQuadraticInSet{T}() + +A `Bool` indicating whether the solver or model supports +a constraint of of the form "quadratic expression" in ``S`` where ``S`` +is a set of type `T`. +""" +struct SupportsQuadraticInSet{T} <: AbstractAttribute end From 9ce67c1eb172bd82c33cec9fecfd803ad58fb8bd Mon Sep 17 00:00:00 2001 From: Joey Huchette Date: Thu, 15 Jun 2017 10:53:10 -0400 Subject: [PATCH 30/83] Add writeproblem, getbasis --- src/SolverInterface/SolverInterface.jl | 5 +++++ src/SolverInterface/attributes.jl | 7 +++++++ 2 files changed, 12 insertions(+) diff --git a/src/SolverInterface/SolverInterface.jl b/src/SolverInterface/SolverInterface.jl index a76fd9d..ce4af2c 100644 --- a/src/SolverInterface/SolverInterface.jl +++ b/src/SolverInterface/SolverInterface.jl @@ -50,7 +50,12 @@ function freemodel! end # TODO function loadproblem! end +""" + writeproblem(m::AbstractLinearQuadraticModel, filename::String) +Writes the current problem data to the given file. Supported file types are solver-dependent. +""" +function writeproblem end # these could change to attributes that can be set on a model *or solver* # solver parameters, may be implemented by AbstractMathProgModel or AbstractMathProgSolver diff --git a/src/SolverInterface/attributes.jl b/src/SolverInterface/attributes.jl index e3f9cc1..bbc4ded 100644 --- a/src/SolverInterface/attributes.jl +++ b/src/SolverInterface/attributes.jl @@ -257,6 +257,13 @@ end ConstraintDual() = ConstraintDual(1) +""" + SolutionBasis() + +Returns the basis set for the optimal solution in the form `(cbasis,rbasis)`, where both return values are vectors of symbols. The vector `cbasis` indexes the columns of the constraint matrix, while `rbasis` indexes the rows (values indicate whether the constraint is active at a lower/upper bound). The entries take value `:Basic` if the element is basic, `:NonbasicAtLower` if it is nonbasic at a lower bound, and `:NonbasicAtUpper` if it is nonbasic at upper bound. Other values may appear, taking solver-specific values. Note that this function may not work if the optimization algorithm is not able to provide basis information. +""" +struct SolutionBasis <: AbstractAttribute end + # Termination status """ TerminationStatus() From bc20db933e77eea5cd8f7eb5c8a9953e137832d8 Mon Sep 17 00:00:00 2001 From: Joey Huchette Date: Thu, 15 Jun 2017 11:01:29 -0400 Subject: [PATCH 31/83] Add LinearConstraintCount --- src/SolverInterface/attributes.jl | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/SolverInterface/attributes.jl b/src/SolverInterface/attributes.jl index 7f59f0c..1616d52 100644 --- a/src/SolverInterface/attributes.jl +++ b/src/SolverInterface/attributes.jl @@ -104,6 +104,13 @@ struct Sense <: AbstractAttribute end @enum OptimizationSense MinSense MaxSense +""" + LinearConstraintCount() + +The number of linear constraints in the model. +""" +struct LinearConstraintCount <: AbstractAttribute end + """ SimplexIterations() @@ -146,7 +153,6 @@ The number of variables in the model. """ struct VariableCount <: AbstractAttribute end - """ ConstraintCount{T}() @@ -298,7 +304,6 @@ struct ConstraintDual <: AbstractAttribute end ConstraintDual() = ConstraintDual(1) - """ SolutionBasis() From c772b0d80a569c4a242d26ba62ae100288aa955b Mon Sep 17 00:00:00 2001 From: Miles Lubin Date: Thu, 15 Jun 2017 11:33:26 -0400 Subject: [PATCH 32/83] [ci skip] generalize variable references --- src/SolverInterface/variables.jl | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/SolverInterface/variables.jl b/src/SolverInterface/variables.jl index 1891e8a..8481a38 100644 --- a/src/SolverInterface/variables.jl +++ b/src/SolverInterface/variables.jl @@ -1,12 +1,14 @@ + +struct GenericVariableReference{T} + value::UInt64 +end """ VariableReference A lightweight object used to reference variables in a model. """ -struct VariableReference - value::UInt64 -end +const VariableReference = GenericVariableReference{1} """ candelete(m::AbstractMathProgModel, ref::VariableReference)::Bool From 6661fb8079bc3d6cf0f4c116ec8b54fd3f3fdec9 Mon Sep 17 00:00:00 2001 From: Joey Huchette Date: Thu, 15 Jun 2017 11:52:08 -0400 Subject: [PATCH 33/83] Remove LinearConstraintCount; change basis getters --- src/SolverInterface/attributes.jl | 32 +++++++++++++++++++------------ 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/src/SolverInterface/attributes.jl b/src/SolverInterface/attributes.jl index 1616d52..14e41f0 100644 --- a/src/SolverInterface/attributes.jl +++ b/src/SolverInterface/attributes.jl @@ -104,13 +104,6 @@ struct Sense <: AbstractAttribute end @enum OptimizationSense MinSense MaxSense -""" - LinearConstraintCount() - -The number of linear constraints in the model. -""" -struct LinearConstraintCount <: AbstractAttribute end - """ SimplexIterations() @@ -216,7 +209,6 @@ to warm-start the solve. """ struct VariableUpperBoundDualStart <: AbstractAttribute end - """ VariableLowerBound() @@ -224,7 +216,6 @@ Lower-bound constraints on variables. `-Inf` is valid as no bound. """ struct VariableLowerBound <: AbstractAttribute end - """ VariableUpperBound() @@ -263,6 +254,17 @@ struct VariableUpperBoundDual <: AbstractAttribute end VariableUpperBoundDual() = VariableUpperBoundDual(1) +""" + VariableBasisStatus() + +Returns the `VariableBasisStatusCode` of a given variable, with respect to an available optimal solution basis. + * `Basic`: variable is in the basis. + * `NonbasicAtLower`: variable is not in the basis and is at its lower bound. + * `NonbasicAtUpper`: variable is not in the basis and is at its upper bound. + * `SuperBasic`: variable is not in the basis but is also not at one of its bounds. +""" +struct VariableBasisStatus <: AbstractAttribute end +@enum VariableBasisStatusCode Basic NonbasicAtLower NonbasicAtUpper SuperBasic # Constraint attributes @@ -305,11 +307,17 @@ end ConstraintDual() = ConstraintDual(1) """ - SolutionBasis() + ConstraintBasisStatus() -Returns the basis set for the optimal solution in the form `(cbasis,rbasis)`, where both return values are vectors of symbols. The vector `cbasis` indexes the columns of the constraint matrix, while `rbasis` indexes the rows (values indicate whether the constraint is active at a lower/upper bound). The entries take value `:Basic` if the element is basic, `:NonbasicAtLower` if it is nonbasic at a lower bound, and `:NonbasicAtUpper` if it is nonbasic at upper bound. Other values may appear, taking solver-specific values. Note that this function may not work if the optimization algorithm is not able to provide basis information. +Returns the `ConstraintBasisStatusCode` of a given constraint, with respect to an available optimal solution basis. + * `Basic`: constraint is in the basis, i.e. the corresponding slack variable is in the basis. + * `Nonbasic`: constraint is not in the basis. """ -struct SolutionBasis <: AbstractAttribute end +struct ConstraintBasisStatus <: AbstractAttribute end +@enum ConstraintBasisStatusCode Basic Nonbasic + + + # Termination status """ From c44a0ff2e00cc67dab2ecf599079d2333d825905 Mon Sep 17 00:00:00 2001 From: Joey Huchette Date: Thu, 15 Jun 2017 12:02:18 -0400 Subject: [PATCH 34/83] Tweak docs for basis attributes --- src/SolverInterface/attributes.jl | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/SolverInterface/attributes.jl b/src/SolverInterface/attributes.jl index 14e41f0..a170e76 100644 --- a/src/SolverInterface/attributes.jl +++ b/src/SolverInterface/attributes.jl @@ -258,12 +258,18 @@ VariableUpperBoundDual() = VariableUpperBoundDual(1) VariableBasisStatus() Returns the `VariableBasisStatusCode` of a given variable, with respect to an available optimal solution basis. +""" +struct VariableBasisStatus <: AbstractAttribute end + +""" + VariableBasisStatusCode + +An Enum of possible values for the `VariableBasisStatus` attribute. This explains the status of a given variable with respect to an optimal solution basis. Possible values are: * `Basic`: variable is in the basis. * `NonbasicAtLower`: variable is not in the basis and is at its lower bound. * `NonbasicAtUpper`: variable is not in the basis and is at its upper bound. * `SuperBasic`: variable is not in the basis but is also not at one of its bounds. """ -struct VariableBasisStatus <: AbstractAttribute end @enum VariableBasisStatusCode Basic NonbasicAtLower NonbasicAtUpper SuperBasic # Constraint attributes @@ -310,10 +316,16 @@ ConstraintDual() = ConstraintDual(1) ConstraintBasisStatus() Returns the `ConstraintBasisStatusCode` of a given constraint, with respect to an available optimal solution basis. +""" +struct ConstraintBasisStatus <: AbstractAttribute end + +""" + ConstraintBasisStatusCode + +An Enum of possible values for the `ConstraintBasisStatus` attribute. This explains the status of a given constraint with respect to an optimal solution basis. Possible values are: * `Basic`: constraint is in the basis, i.e. the corresponding slack variable is in the basis. * `Nonbasic`: constraint is not in the basis. """ -struct ConstraintBasisStatus <: AbstractAttribute end @enum ConstraintBasisStatusCode Basic Nonbasic From 8c6da9421971877246a7123af826283465d40434 Mon Sep 17 00:00:00 2001 From: odow Date: Thu, 15 Jun 2017 13:17:57 -0400 Subject: [PATCH 35/83] Modify constraints --- src/SolverInterface/constraints.jl | 54 ++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/src/SolverInterface/constraints.jl b/src/SolverInterface/constraints.jl index 7fdead8..499896f 100644 --- a/src/SolverInterface/constraints.jl +++ b/src/SolverInterface/constraints.jl @@ -75,3 +75,57 @@ x_{varidx} \\in S where `varidx` specifies the indices of the subvector of `x`. """ function addconstraint! end + +""" + modifyconstraint!(m::AbstractMathProgModel, c::ConstraintReference, i::Int, args...) + +Modify elements of the `i`'th row of the constraint `c` depending on the +arguments `args`. The `i`'th row will have the form +```math + a_i^T + b_i + \\frac{1}{2}x^TQ_ix \\in S +``` +There are three cases. + +# Modify Constant term + + modifyconstraint!(m::AbstractMathProgModel, c::ConstraintReference, i::Int, b) + +Set the constant term of the `i`'th row in the constraint `c` to `b`. + +### Examples + + modifyconstraint!(m, c, 1, 1.0) + +# Modify Linear term + +modifyconstraint!(m::AbstractMathProgModel, c::ConstraintReference, i::Int, a_varidx, a_coef) + +Set elements given by `a_varidx` in the linear term of the `i`'th element in the +constraint `c` to `a_coef`. Either `a_varidx` and `a_coef` are both singletons, +or they should be collections with equal length. + +The behaviour of duplicate entries in `a_varidx` is undefined. + +### Examples + + modifyconstraint!(m, c, v, 1.0) + modifyconstraint!(m, c, [v1, v2], [1.0, 2.0]) + +# Modify Quadratic term + + modifyconstraint!(m::AbstractMathProgModel, c::ConstraintReference, i::Int, Q_vari, Q_varj, Q_coef) + +Set the elements in the quadratic term of the `i`'th element of the constraint `c` +specified by the triplets `Q_vari`, `Q_varj`, and `Q_coef`. Off-diagonal entries +will be mirrored. `Q_vari`, `Q_varj` should be collections of `VariableReference` +objects. + +The behaviour of duplicate entries is undefined. If entries for both ``(i,j)`` +and ``(j,i)`` are provided, these are considered duplicate terms. + +### Examples + + modifyconstraint!(m, c, v1, v2, 1.0) + modifyconstraint!(m, c, [v1, v2], [v1, v1], [1.0, 2.0]) +""" +function modifyconstraint! end From 90fb1e0a365abf9b9b4e5d3f4a8c84128f2c1f24 Mon Sep 17 00:00:00 2001 From: odow Date: Thu, 15 Jun 2017 14:09:45 -0400 Subject: [PATCH 36/83] Begin objectives --- src/SolverInterface/objectives.jl | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 src/SolverInterface/objectives.jl diff --git a/src/SolverInterface/objectives.jl b/src/SolverInterface/objectives.jl new file mode 100644 index 0000000..0c18834 --- /dev/null +++ b/src/SolverInterface/objectives.jl @@ -0,0 +1,19 @@ +""" + setobjective!(m::AbstractMathProgModel, N::Int, b, a_varidx, a_coef, Q_vari, Q_varj, Q_coef) + +Set the `N`'th objective in the model `m` to be +```math +a^Tx + b + \\frac{1}{2}x^TQx +``` +where ``a`` is a sparse vector specified in tuple form by `a_varidx`, and +`a_coef`; ``b`` is a scalar; and the symmetric matrix ``Q`` is defined by the +triplets in `Q_vari`, `Q_varj`, `Q_coef`. + +Duplicate indices in either ``A`` or a ``Q`` matrix are accepted and will be +summed together. Off-diagonal entries of ``Q`` will be mirrored, so either the +upper triangular or lower triangular entries of ``Q`` should be provided. If +entries for both ``(i,j)`` and ``(j,i)`` are provided, these are considered +duplicate terms. `a_varidx`, `Q_vari`, `Q_varj` should be collections of +`VariableReference` objects. +""" +function setobjective! end From d4a9e82b04dba97d75d6c8cc18844538a76ddba9 Mon Sep 17 00:00:00 2001 From: odow Date: Thu, 15 Jun 2017 14:23:23 -0400 Subject: [PATCH 37/83] modify and get objective --- src/SolverInterface/objectives.jl | 62 +++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/src/SolverInterface/objectives.jl b/src/SolverInterface/objectives.jl index 0c18834..bd9d8bc 100644 --- a/src/SolverInterface/objectives.jl +++ b/src/SolverInterface/objectives.jl @@ -17,3 +17,65 @@ duplicate terms. `a_varidx`, `Q_vari`, `Q_varj` should be collections of `VariableReference` objects. """ function setobjective! end + +""" + modifyobjective!(m::AbstractMathProgModel, i::Int, args...) + +Modify elements of the `i`'th objective depending on the +arguments `args`. The `i`'th objective will have the form: +```math + a_i^T + b_i + \\frac{1}{2}x^TQ_ix +``` +There are three cases. + +# Modify Constant term + + modifyobjective!(m::AbstractMathProgModel, i::Int, b) + +Set the constant term of the `i`'th row objective to `b`. + +### Examples + + modifyobjective!(m, 1, 1.0) + +# Modify Linear term + + modifyobjective!(m::AbstractMathProgModel, i::Int, a_varidx, a_coef) + +Set elements given by `a_varidx` in the linear term of the `i`'th objective to +`a_coef`. Either `a_varidx` and `a_coef` are both singletons, or they should be +collections with equal length. + +The behaviour of duplicate entries in `a_varidx` is undefined. + +### Examples + + modifyobjective!(m, 1, v, 1.0) + modifyobjective!(m, 1, [v1, v2], [1.0, 2.0]) + +# Modify Quadratic term + + modifyobjective!(m::AbstractMathProgModel, i::Int, Q_vari, Q_varj, Q_coef) + +Set the elements in the quadratic term of the `i`'th objective specified by the +triplets `Q_vari`, `Q_varj`, and `Q_coef`. Off-diagonal entries will be mirrored. +`Q_vari`, `Q_varj` should be collections of `VariableReference` objects. + +The behaviour of duplicate entries is undefined. If entries for both ``(i,j)`` +and ``(j,i)`` are provided, these are considered duplicate terms. + +### Examples + + modifyobjective!(m, 1, v1, v2, 1.0) + modifyobjective!(m, 1, [v1, v2], [v1, v1], [1.0, 2.0]) +""" +function modifyobjective! end + +""" + getobjective(m, i:Int) + +Returns the `i`'th objective as the tuple `(b, a_varidx, a_coef, Q_vari, Q_varj, Q_coef)`. + +The elements in the tuple are the same as those defined in `addobjective!`. +""" +function getobjective end From 86f937747a0ba348d64d8aba3004cebd6fec32ee Mon Sep 17 00:00:00 2001 From: odow Date: Thu, 15 Jun 2017 14:39:56 -0400 Subject: [PATCH 38/83] Multi-objective attributes --- src/SolverInterface/attributes.jl | 46 ++++++++++++++++++++++++------- 1 file changed, 36 insertions(+), 10 deletions(-) diff --git a/src/SolverInterface/attributes.jl b/src/SolverInterface/attributes.jl index a170e76..83c8a4d 100644 --- a/src/SolverInterface/attributes.jl +++ b/src/SolverInterface/attributes.jl @@ -64,29 +64,48 @@ end # Scalar attributes """ - ObjectiveValue(N) + ObjectiveValue(objectiveindex::Int, resultindex::Int) + ObjectiveValue(;objectiveindex::Int=1, resultindex::Int=1) ObjectiveValue() -The objective value of the primal result `N`. If `N` is omitted, it defaults to 1. +The objective value of the `resultindex`'th primal result of the `objectiveindex`'th objective. + +Both `objectiveindex` and `resultindex` default to 1. """ struct ObjectiveValue <: AbstractAttribute - N::Int + objectiveindex::Int + resultindex::Int end -ObjectiveValue() = ObjectiveValue(1) +ObjectiveValue() = ObjectiveValue(1, 1) +ObjectiveValue(;objectiveindex=1, resultindex=1) = ObjectiveValue(objectiveindex, resultindex) """ + ObjectiveBound(N::Int) ObjectiveBound() -The best known bound on the optimal objective value. +The best known bound on the optimal objective value for the `N`'th objective. + +If `N` is not specified it defaults to 1. """ -struct ObjectiveBound <: AbstractAttribute end +struct ObjectiveBound <: AbstractAttribute + N::Int +end +ObjectiveBound() = ObjectiveBound(1) """ + RelativeGap(N::Int) RelativeGap() -The final relative optimality gap as optimization terminated. That is, ``\\frac{|b-f|}{|f|}``, where ``b`` is the best bound and ``f`` is the best feasible objective value. +The final relative optimality gap of the `N`'th objective as optimization terminated. +That is, ``\\frac{|b-f|}{|f|}``, where ``b`` is the best bound and ``f`` is the +best feasible objective value. + +If `N` is not specified it defaults to 1. """ -struct RelativeGap <: AbstractAttribute end +struct RelativeGap <: AbstractAttribute + N::Int +end +RelativeGap() = RelativeGap(1) """ SolveTime() @@ -96,11 +115,18 @@ The total elapsed solution time (in seconds) as reported by the solver. struct SolveTime <: AbstractAttribute end """ + Sense(N::Int) Sense() -The optimization sense of the model, an `OptimizationSense` with value `MinSense` or `MaxSense`. +The optimization sense of `N`'th objective in the model. It is an +`OptimizationSense` with value `MinSense` or `MaxSense`. + +If `N` is not specified it defaults to 1. """ -struct Sense <: AbstractAttribute end +struct Sense <: AbstractAttribute + N::Int +end +Sense() = Sense(1) @enum OptimizationSense MinSense MaxSense From a0e44d3659ca0be95172452c105d3b09d8ff8374 Mon Sep 17 00:00:00 2001 From: Joey Huchette Date: Thu, 15 Jun 2017 14:47:19 -0400 Subject: [PATCH 39/83] Same basis return statuses for both variables and constraints --- src/SolverInterface/attributes.jl | 28 ++++++++++------------------ 1 file changed, 10 insertions(+), 18 deletions(-) diff --git a/src/SolverInterface/attributes.jl b/src/SolverInterface/attributes.jl index a170e76..44a2e07 100644 --- a/src/SolverInterface/attributes.jl +++ b/src/SolverInterface/attributes.jl @@ -257,20 +257,21 @@ VariableUpperBoundDual() = VariableUpperBoundDual(1) """ VariableBasisStatus() -Returns the `VariableBasisStatusCode` of a given variable, with respect to an available optimal solution basis. +Returns the `BasisStatusCode` of a given variable, with respect to an available optimal solution basis. """ struct VariableBasisStatus <: AbstractAttribute end """ - VariableBasisStatusCode + BasisStatusCode -An Enum of possible values for the `VariableBasisStatus` attribute. This explains the status of a given variable with respect to an optimal solution basis. Possible values are: - * `Basic`: variable is in the basis. - * `NonbasicAtLower`: variable is not in the basis and is at its lower bound. - * `NonbasicAtUpper`: variable is not in the basis and is at its upper bound. - * `SuperBasic`: variable is not in the basis but is also not at one of its bounds. +An Enum of possible values for the `VariableBasisStatus` and `ConstraintBasisStatus` attribute. This explains the status of a given element with respect to an optimal solution basis. Possible values are: + * `Basic`: element is in the basis. + * `Nonbasic`: element is not in the basis. + * `NonbasicAtLower`: element is not in the basis and is at its lower bound. + * `NonbasicAtUpper`: element is not in the basis and is at its upper bound. + * `SuperBasic`: element is not in the basis but is also not at one of its bounds. """ -@enum VariableBasisStatusCode Basic NonbasicAtLower NonbasicAtUpper SuperBasic +@enum BasisStatusCode Basic Nonbasic NonbasicAtLower NonbasicAtUpper SuperBasic # Constraint attributes @@ -315,19 +316,10 @@ ConstraintDual() = ConstraintDual(1) """ ConstraintBasisStatus() -Returns the `ConstraintBasisStatusCode` of a given constraint, with respect to an available optimal solution basis. +Returns the `BasisStatusCode` of a given constraint, with respect to an available optimal solution basis. """ struct ConstraintBasisStatus <: AbstractAttribute end -""" - ConstraintBasisStatusCode - -An Enum of possible values for the `ConstraintBasisStatus` attribute. This explains the status of a given constraint with respect to an optimal solution basis. Possible values are: - * `Basic`: constraint is in the basis, i.e. the corresponding slack variable is in the basis. - * `Nonbasic`: constraint is not in the basis. -""" -@enum ConstraintBasisStatusCode Basic Nonbasic - From 4a62e4bad2d8545ea17f9f4961c688691a6bffe6 Mon Sep 17 00:00:00 2001 From: odow Date: Thu, 15 Jun 2017 14:52:12 -0400 Subject: [PATCH 40/83] Revert objective attributes --- src/SolverInterface/attributes.jl | 44 +++++++------------------------ 1 file changed, 10 insertions(+), 34 deletions(-) diff --git a/src/SolverInterface/attributes.jl b/src/SolverInterface/attributes.jl index 83c8a4d..94d07d3 100644 --- a/src/SolverInterface/attributes.jl +++ b/src/SolverInterface/attributes.jl @@ -64,48 +64,31 @@ end # Scalar attributes """ - ObjectiveValue(objectiveindex::Int, resultindex::Int) - ObjectiveValue(;objectiveindex::Int=1, resultindex::Int=1) - ObjectiveValue() + ObjectiveValue(resultidx::Int=1, objectiveindex::Int=1) The objective value of the `resultindex`'th primal result of the `objectiveindex`'th objective. -Both `objectiveindex` and `resultindex` default to 1. +Both `resultindex` and `objectiveindex` default to 1. """ struct ObjectiveValue <: AbstractAttribute - objectiveindex::Int resultindex::Int + objectiveindex::Int end -ObjectiveValue() = ObjectiveValue(1, 1) -ObjectiveValue(;objectiveindex=1, resultindex=1) = ObjectiveValue(objectiveindex, resultindex) +ObjectiveValue(resultindex=1, objectiveindex=1) = ObjectiveValue(resultindex, objectiveindex) """ - ObjectiveBound(N::Int) ObjectiveBound() -The best known bound on the optimal objective value for the `N`'th objective. - -If `N` is not specified it defaults to 1. +The best known bound on the optimal objective value. """ -struct ObjectiveBound <: AbstractAttribute - N::Int -end -ObjectiveBound() = ObjectiveBound(1) +struct ObjectiveBound <: AbstractAttribute end """ - RelativeGap(N::Int) RelativeGap() -The final relative optimality gap of the `N`'th objective as optimization terminated. -That is, ``\\frac{|b-f|}{|f|}``, where ``b`` is the best bound and ``f`` is the -best feasible objective value. - -If `N` is not specified it defaults to 1. +The final relative optimality gap as optimization terminated. That is, ``\\frac{|b-f|}{|f|}``, where ``b`` is the best bound and ``f`` is the best feasible objective value. """ -struct RelativeGap <: AbstractAttribute - N::Int -end -RelativeGap() = RelativeGap(1) +struct RelativeGap <: AbstractAttribute end """ SolveTime() @@ -115,18 +98,11 @@ The total elapsed solution time (in seconds) as reported by the solver. struct SolveTime <: AbstractAttribute end """ - Sense(N::Int) Sense() -The optimization sense of `N`'th objective in the model. It is an -`OptimizationSense` with value `MinSense` or `MaxSense`. - -If `N` is not specified it defaults to 1. +The optimization sense of the model, an `OptimizationSense` with value `MinSense` or `MaxSense`. """ -struct Sense <: AbstractAttribute - N::Int -end -Sense() = Sense(1) +struct Sense <: AbstractAttribute end @enum OptimizationSense MinSense MaxSense From a6dfeffdb58e0dddc366d14123972123b4775636 Mon Sep 17 00:00:00 2001 From: odow Date: Thu, 15 Jun 2017 14:57:26 -0400 Subject: [PATCH 41/83] include file and fix typo --- src/SolverInterface/SolverInterface.jl | 1 + src/SolverInterface/objectives.jl | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/SolverInterface/SolverInterface.jl b/src/SolverInterface/SolverInterface.jl index ce4af2c..94077d1 100644 --- a/src/SolverInterface/SolverInterface.jl +++ b/src/SolverInterface/SolverInterface.jl @@ -65,6 +65,7 @@ include("variables.jl") include("constraints.jl") include("sets.jl") include("attributes.jl") +include("objectives.jl") #include("LinearQuadratic.jl") #include("callbacks.jl") diff --git a/src/SolverInterface/objectives.jl b/src/SolverInterface/objectives.jl index bd9d8bc..4f16631 100644 --- a/src/SolverInterface/objectives.jl +++ b/src/SolverInterface/objectives.jl @@ -24,7 +24,7 @@ function setobjective! end Modify elements of the `i`'th objective depending on the arguments `args`. The `i`'th objective will have the form: ```math - a_i^T + b_i + \\frac{1}{2}x^TQ_ix + a_i^Tx + b_i + \\frac{1}{2}x^TQ_ix ``` There are three cases. From 9cdad136b9d157a2934909bb80dd21125cf13e72 Mon Sep 17 00:00:00 2001 From: Miles Lubin Date: Thu, 15 Jun 2017 15:01:01 -0400 Subject: [PATCH 42/83] fix constructor for ObjectiveValue --- src/SolverInterface/attributes.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/SolverInterface/attributes.jl b/src/SolverInterface/attributes.jl index 1a81ea5..8f63346 100644 --- a/src/SolverInterface/attributes.jl +++ b/src/SolverInterface/attributes.jl @@ -73,8 +73,8 @@ Both `resultindex` and `objectiveindex` default to 1. struct ObjectiveValue <: AbstractAttribute resultindex::Int objectiveindex::Int + (::Type{ObjectiveValue})(resultindex=1, objectiveindex=1) = new(resultindex, objectiveindex) end -ObjectiveValue(resultindex=1, objectiveindex=1) = ObjectiveValue(resultindex, objectiveindex) """ ObjectiveBound() From 838db374e07fb089a8e7ac259def5de7e4da6dd0 Mon Sep 17 00:00:00 2001 From: ccoffrin Date: Thu, 15 Jun 2017 15:03:59 -0400 Subject: [PATCH 43/83] making latest docs build from break_everything branch --- docs/make.jl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/make.jl b/docs/make.jl index 0c6dc59..2160a1c 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -19,5 +19,6 @@ deploydocs( osname = "linux", julia = "0.6", deps = nothing, - make = nothing + make = nothing, + latest = "break_everything" ) From 8868c8529f6b1e19fde72efe3e98c67094254526 Mon Sep 17 00:00:00 2001 From: Miles Lubin Date: Thu, 15 Jun 2017 15:06:28 -0400 Subject: [PATCH 44/83] collapse high-level interface docs into one file --- docs/make.jl | 4 +--- docs/src/linearprog.md | 11 ----------- docs/src/mixedintprog.md | 5 ----- docs/src/quadprog.md | 9 --------- 4 files changed, 1 insertion(+), 28 deletions(-) delete mode 100644 docs/src/linearprog.md delete mode 100644 docs/src/mixedintprog.md delete mode 100644 docs/src/quadprog.md diff --git a/docs/make.jl b/docs/make.jl index 0c6dc59..39965bf 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -5,9 +5,7 @@ makedocs( sitename = "MathProgBase", pages = [ "Introduction" => "index.md", - "Linear Programming" => "linearprog.md", - "Mixed-Integer Programming" => "mixedintprog.md", - "Quadratic Programming" => "quadprog.md", + "High-level Interfaces" => "highlevel.md", "Solver Interface" => "solverinterface.md", "Choosing Solver" => "choosingsolver.md" ] diff --git a/docs/src/linearprog.md b/docs/src/linearprog.md deleted file mode 100644 index c048304..0000000 --- a/docs/src/linearprog.md +++ /dev/null @@ -1,11 +0,0 @@ -# Linear Programming - -```@meta - CurrentModule = MathProgBase -``` - -```@docs -linprog -buildlp -solvelp -``` diff --git a/docs/src/mixedintprog.md b/docs/src/mixedintprog.md deleted file mode 100644 index 5f37b59..0000000 --- a/docs/src/mixedintprog.md +++ /dev/null @@ -1,5 +0,0 @@ -# Mixed-integer Programming - -```@docs -mixintprog -``` diff --git a/docs/src/quadprog.md b/docs/src/quadprog.md deleted file mode 100644 index 8a7600a..0000000 --- a/docs/src/quadprog.md +++ /dev/null @@ -1,9 +0,0 @@ -# Quadratic Programming - -```@meta - CurrentModule = MathProgBase -``` - -```@docs -quadprog -``` From e9075b47523cb243747170dc45736acb07a50184 Mon Sep 17 00:00:00 2001 From: Miles Lubin Date: Thu, 15 Jun 2017 15:36:08 -0400 Subject: [PATCH 45/83] restructure docs into separate files --- docs/make.jl | 9 ++- docs/src/attributes.md | 61 ++++++++++++++++ docs/src/basics.md | 17 +++++ docs/src/constraints.md | 12 +++ docs/src/duals.md | 7 ++ docs/src/highlevel.md | 23 ++++++ docs/src/sets.md | 14 ++++ docs/src/solverinterface.md | 141 ------------------------------------ docs/src/statuscodes.md | 28 +++++++ docs/src/variables.md | 14 ++++ 10 files changed, 184 insertions(+), 142 deletions(-) create mode 100644 docs/src/attributes.md create mode 100644 docs/src/basics.md create mode 100644 docs/src/constraints.md create mode 100644 docs/src/duals.md create mode 100644 docs/src/highlevel.md create mode 100644 docs/src/sets.md delete mode 100644 docs/src/solverinterface.md create mode 100644 docs/src/statuscodes.md create mode 100644 docs/src/variables.md diff --git a/docs/make.jl b/docs/make.jl index 39965bf..a31f4fb 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -6,7 +6,14 @@ makedocs( pages = [ "Introduction" => "index.md", "High-level Interfaces" => "highlevel.md", - "Solver Interface" => "solverinterface.md", + "Solver Interface" => [ + "Basics" => "basics.md", + "Variables" => "variables.md", + "Constraints" => "constraints.md", + "Sets" => "sets.md", + "Attributes" => "attributes.md", + "Status Codes" => "statuscodes.md", + "Duals" => "duals.md"], "Choosing Solver" => "choosingsolver.md" ] ) diff --git a/docs/src/attributes.md b/docs/src/attributes.md new file mode 100644 index 0000000..a0cccba --- /dev/null +++ b/docs/src/attributes.md @@ -0,0 +1,61 @@ +```@meta +CurrentModule = MathProgBase +``` + +These are used to get and set properties of the model. + +```@docs +AbstractAttribute +cangetattribute +getattribute +cansetattribute +setattribute! +``` + +## Scalar Attributes + +```@docs +ObjectiveValue +ObjectiveBound +RelativeGap +SolveTime +Sense +SimplexIterations +BarrierIterations +NodeCount +RawSolver +ResultCount +VariableCount +ConstraintCount +SupportsVariablesInSet +SupportsAffineInSet +SupportsQuadraticInSet +``` + +## Variable Attributes + +These attributes are associated with variables. Calls to `getattribute` and `setattribute!` should include as an argument a single `VariableReference` or a vector of `VariableReference` objects. + +```@docs +VariablePrimalStart +VariableLowerBoundDualStart +VariableUpperBoundDualStart +VariableLowerBound +VariableUpperBound +VariablePrimal +VariableLowerBoundDual +VariableUpperBoundDual +``` + +## Constraint Attributes + +These attributes are associated with constraints. Calls to `getattribute` and `setattribute!` should include as an argument a single `ConstraintReference` or a vector of `ConstriaintReference{T}` objects. + +```@docs +ConstraintPrimalStart +ConstraintDualStart +ConstraintPrimal +ConstraintDual +``` + + diff --git a/docs/src/basics.md b/docs/src/basics.md new file mode 100644 index 0000000..3f0bc5a --- /dev/null +++ b/docs/src/basics.md @@ -0,0 +1,17 @@ + +```@meta +CurrentModule = MathProgBase +``` + +Some introduction to MPB API. List basic standalone methods. + +```@docs +AbstractMathProgModel +AbstractMathProgSolver +``` + + +```@docs +optimize! +freemodel! +``` diff --git a/docs/src/constraints.md b/docs/src/constraints.md new file mode 100644 index 0000000..71dba22 --- /dev/null +++ b/docs/src/constraints.md @@ -0,0 +1,12 @@ +```@meta +CurrentModule = MathProgBase +``` + +How to add constraints. +```@docs +ConstraintReference +candelete(::AbstractMathProgModel,::ConstraintReference) +isvalid(::AbstractMathProgModel,::ConstraintReference) +delete!(::AbstractMathProgModel,::ConstraintReference) +addconstraint! +``` diff --git a/docs/src/duals.md b/docs/src/duals.md new file mode 100644 index 0000000..b25b1b3 --- /dev/null +++ b/docs/src/duals.md @@ -0,0 +1,7 @@ +```@meta +CurrentModule = MathProgBase +``` + + +We take the convention that duals on variable lower bounds should be nonnegative, duals on variable upper bounds should be nonpositive, and duals on closed convex cones should belong to the dual cone. + diff --git a/docs/src/highlevel.md b/docs/src/highlevel.md new file mode 100644 index 0000000..21deb66 --- /dev/null +++ b/docs/src/highlevel.md @@ -0,0 +1,23 @@ +```@meta + CurrentModule = MathProgBase +``` + +## Linear Programming + +```@docs +linprog +buildlp +solvelp +``` + +## Mixed-integer Programming + +```@docs +mixintprog +``` + +## Quadratic Programming + +```@docs +quadprog +``` diff --git a/docs/src/sets.md b/docs/src/sets.md new file mode 100644 index 0000000..b11ae0d --- /dev/null +++ b/docs/src/sets.md @@ -0,0 +1,14 @@ +```@meta +CurrentModule = MathProgBase +``` + + +List of sets. +```@docs +NonNegative +NonPositive +Zero +Interval +Integers +Binaries +``` diff --git a/docs/src/solverinterface.md b/docs/src/solverinterface.md deleted file mode 100644 index 159fd75..0000000 --- a/docs/src/solverinterface.md +++ /dev/null @@ -1,141 +0,0 @@ -# Solver Interface - -```@meta -CurrentModule = MathProgBase -``` - -```@docs -AbstractMathProgModel -AbstractMathProgSolver -``` - -## Basic Methods - -```@docs -optimize! -freemodel! -``` - -## Variables - -```@docs -VariableReference -candelete(::AbstractMathProgModel,::VariableReference) -isvalid(::AbstractMathProgModel,::VariableReference) -delete!(::AbstractMathProgModel,::VariableReference) -addvariables! -addvariable! -``` - -## Constraints - -How to add constraints. -```@docs -ConstraintReference -candelete(::AbstractMathProgModel,::ConstraintReference) -isvalid(::AbstractMathProgModel,::ConstraintReference) -delete!(::AbstractMathProgModel,::ConstraintReference) -addconstraint! -``` - -## Sets - - - -List of sets. -```@docs -NonNegative -NonPositive -Zero -Interval -Integers -Binaries -``` -## Attributes - -These are used to get and set properties of the model. - -```@docs -AbstractAttribute -cangetattribute -getattribute -cansetattribute -setattribute! -``` - -### Scalar Attributes - -```@docs -ObjectiveValue -ObjectiveBound -RelativeGap -SolveTime -Sense -SimplexIterations -BarrierIterations -NodeCount -RawSolver -ResultCount -VariableCount -ConstraintCount -SupportsVariablesInSet -SupportsAffineInSet -SupportsQuadraticInSet -``` - -### Variable Attributes - -These attributes are associated with variables. Calls to `getattribute` and `setattribute!` should include as an argument a single `VariableReference` or a vector of `VariableReference` objects. - -```@docs -VariablePrimalStart -VariableLowerBoundDualStart -VariableUpperBoundDualStart -VariableLowerBound -VariableUpperBound -VariablePrimal -VariableLowerBoundDual -VariableUpperBoundDual -``` - -### Constraint Attributes - -These attributes are associated with constraints. Calls to `getattribute` and `setattribute!` should include as an argument a single `ConstraintReference` or a vector of `ConstriaintReference{T}` objects. - -```@docs -ConstraintPrimalStart -ConstraintDualStart -ConstraintPrimal -ConstraintDual -``` - - - -## Termination Status - -The `TerminationStatus` attribute is meant to explain the reason why the solver stopped executing. The value of the attribute is of type `TerminationStatusCode`. - -```@docs -TerminationStatus -TerminationStatusCode -``` - -## Result Status - -The `PrimalStatus` and `DualStatus` attributes are meant to explain how to interpret the result returned by the solver. The value of the attributes are of type `ResultStatusCode`. - -```@docs -PrimalStatus -DualStatus -ResultStatusCode -``` - -## Basis Status - -TODO: attributes and status codes for LP basis status - - -## Duals - -We take the convention that duals on variable lower bounds should be nonnegative, duals on variable upper bounds should be nonpositive, and duals on closed convex cones should belong to the dual cone. - diff --git a/docs/src/statuscodes.md b/docs/src/statuscodes.md new file mode 100644 index 0000000..3f8af99 --- /dev/null +++ b/docs/src/statuscodes.md @@ -0,0 +1,28 @@ +```@meta +CurrentModule = MathProgBase +``` + + +## Termination Status + +The `TerminationStatus` attribute is meant to explain the reason why the solver stopped executing. The value of the attribute is of type `TerminationStatusCode`. + +```@docs +TerminationStatus +TerminationStatusCode +``` + +## Result Status + +The `PrimalStatus` and `DualStatus` attributes are meant to explain how to interpret the result returned by the solver. The value of the attributes are of type `ResultStatusCode`. + +```@docs +PrimalStatus +DualStatus +ResultStatusCode +``` + +## Basis Status + +TODO: attributes and status codes for LP basis status + diff --git a/docs/src/variables.md b/docs/src/variables.md new file mode 100644 index 0000000..61fa9c8 --- /dev/null +++ b/docs/src/variables.md @@ -0,0 +1,14 @@ + +```@meta +CurrentModule = MathProgBase +``` + +```@docs +VariableReference +candelete(::AbstractMathProgModel,::VariableReference) +isvalid(::AbstractMathProgModel,::VariableReference) +delete!(::AbstractMathProgModel,::VariableReference) +addvariables! +addvariable! +``` + From 102906cc97851e6ba5fa29a5ace8f522d548bff4 Mon Sep 17 00:00:00 2001 From: Miles Lubin Date: Thu, 15 Jun 2017 15:51:06 -0400 Subject: [PATCH 46/83] comment out interface tests, to be rewritten --- test/conicinterface.jl | 2 ++ test/linproginterface.jl | 3 +++ 2 files changed, 5 insertions(+) diff --git a/test/conicinterface.jl b/test/conicinterface.jl index a1b15ca..6dad8b7 100644 --- a/test/conicinterface.jl +++ b/test/conicinterface.jl @@ -8,6 +8,7 @@ using Base.Test using MathProgBase +""" function coniclineartest(solver::MathProgBase.AbstractMathProgSolver;duals=false, tol=1e-6) @testset "Testing linear problems through conic interface with $solver" begin # Problem LIN1 - all vars in nonneg cone @@ -820,3 +821,4 @@ function conicSDPtest(solver::MathProgBase.AbstractMathProgSolver;duals=true, to end end end +""" diff --git a/test/linproginterface.jl b/test/linproginterface.jl index 1a5976a..c7c868f 100644 --- a/test/linproginterface.jl +++ b/test/linproginterface.jl @@ -2,6 +2,8 @@ using Base.Test using MathProgBase using MathProgBase.SolverInterface + +""" function linprogsolvertest(solver::AbstractMathProgSolver, eps = Base.rtoldefault(Float64)) @testset "Testing LP interface with $solver" begin @testset "Basic interface" begin @@ -471,3 +473,4 @@ function linprogsolvertestextra(solver::AbstractMathProgSolver; eps = Base.rtold end end end +""" From cd9181508f746f4ef96a6fe2d11993e301affc11 Mon Sep 17 00:00:00 2001 From: Oscar Dowson Date: Thu, 15 Jun 2017 15:54:33 -0400 Subject: [PATCH 47/83] Models (#181) * Models * remove solverinterface * NonLinear->NLP --- docs/src/basics.md | 5 ++- src/SolverInterface/SolverInterface.jl | 46 +++++++++++++++++++++----- 2 files changed, 41 insertions(+), 10 deletions(-) diff --git a/docs/src/basics.md b/docs/src/basics.md index 3f0bc5a..f2e8f22 100644 --- a/docs/src/basics.md +++ b/docs/src/basics.md @@ -6,12 +6,15 @@ CurrentModule = MathProgBase Some introduction to MPB API. List basic standalone methods. ```@docs -AbstractMathProgModel +AbstractModel +AbstractNLPModel AbstractMathProgSolver ``` ```@docs +Model +NLPModel optimize! freemodel! ``` diff --git a/src/SolverInterface/SolverInterface.jl b/src/SolverInterface/SolverInterface.jl index 94077d1..857f265 100644 --- a/src/SolverInterface/SolverInterface.jl +++ b/src/SolverInterface/SolverInterface.jl @@ -9,14 +9,6 @@ rewrap_methods = [:getobjbound, :getsolvetime, ] -""" - AbstractMathProgModel - -Abstract supertype which represents a solver's -in-memory representation of an optimization problem. -""" -abstract type AbstractMathProgModel end - # immutable type which we dispatch solvers on """ AbstractMathProgSolver @@ -25,6 +17,42 @@ Abstract supertype for "solver" objects. A solver is a lightweight object used f """ abstract type AbstractMathProgSolver end +""" + AbstractNLPModel + +Abstract supertype which represents a solver's in-memory representation of a +non-linear optimization problem. +""" +abstract type AbstractNLPModel end + +""" + NLPModel(solver::AbstractMathProgSolver) + +Create an instance of `AbstractNLPModel` using the given solver. +""" +function NLPModel end + +""" + AbstractModel + +Abstract supertype which represents a solver's in-memory representation of an +optimization problem. +""" +abstract type AbstractModel end + +""" + Model(solver::AbstractMathProgSolver) + +Create an instance of `AbstractModel` using the given solver. +""" +function Model end + +""" + AbstractMathProgModel + +Union type of both `AbstractNLPModel` and `AbstractModel`. +""" +const AbstractMathProgModel = Union{AbstractNLPModel, AbstractModel} # basic methods methods for AbstractMathProgModel @@ -51,7 +79,7 @@ function freemodel! end function loadproblem! end """ - writeproblem(m::AbstractLinearQuadraticModel, filename::String) + writeproblem(m::AbstractModel, filename::String) Writes the current problem data to the given file. Supported file types are solver-dependent. """ From 402839f176a2db037cee462d55132b4381ba0e39 Mon Sep 17 00:00:00 2001 From: Miles Lubin Date: Thu, 15 Jun 2017 17:27:25 -0400 Subject: [PATCH 48/83] split variable references, specialized affine-in-set constraint --- docs/src/constraints.md | 4 +- src/SolverInterface/SolverInterface.jl | 1 + src/SolverInterface/constraints.jl | 71 ++++++++----------- src/SolverInterface/references.jl | 96 ++++++++++++++++++++++++++ src/SolverInterface/variables.jl | 38 ---------- 5 files changed, 130 insertions(+), 80 deletions(-) create mode 100644 src/SolverInterface/references.jl diff --git a/docs/src/constraints.md b/docs/src/constraints.md index 71dba22..1d55777 100644 --- a/docs/src/constraints.md +++ b/docs/src/constraints.md @@ -4,7 +4,9 @@ CurrentModule = MathProgBase How to add constraints. ```@docs -ConstraintReference +VariablewiseConstraintReference +AffineConstraintReference +QuadraticConstraintReference candelete(::AbstractMathProgModel,::ConstraintReference) isvalid(::AbstractMathProgModel,::ConstraintReference) delete!(::AbstractMathProgModel,::ConstraintReference) diff --git a/src/SolverInterface/SolverInterface.jl b/src/SolverInterface/SolverInterface.jl index 857f265..8ffec8b 100644 --- a/src/SolverInterface/SolverInterface.jl +++ b/src/SolverInterface/SolverInterface.jl @@ -90,6 +90,7 @@ function writeproblem end function setparameters! end include("variables.jl") +include("references.jl") include("constraints.jl") include("sets.jl") include("attributes.jl") diff --git a/src/SolverInterface/constraints.jl b/src/SolverInterface/constraints.jl index 499896f..08411d7 100644 --- a/src/SolverInterface/constraints.jl +++ b/src/SolverInterface/constraints.jl @@ -1,51 +1,16 @@ -""" - ConstraintReference{T} - -A lightweight object used to reference constraints in a model. -The parameter `T` is the type of set constraint referenced. -""" -struct ConstraintReference{T} - value::UInt64 -end - -""" - candelete(m::AbstractMathProgModel, ref::ConstraintReference)::Bool - -Return a `Bool` indicating whether this constraint can be removed from the model `m`. -""" -candelete(m::AbstractMathProgModel, ref::ConstraintReference) = throw(MethodError()) - -""" - isvalid(m::AbstractMathProgModel, ref::ConstraintReference)::Bool - -Return a `Bool` indicating whether this reference is valid -for an active constraint in the model `m`. -""" -isvalid(m::AbstractMathProgModel, ref::ConstraintReference) = throw(MethodError()) - -""" - delete!(m::AbstractMathProgModel, ref::ConstraintReference) - -Delete the referenced constraint from the model. - delete!(m::AbstractMathProgModel, refs::Vector{ConstraintReference}) - -Delete the referenced constraints in the vector `refs` from the model. -""" -Base.delete!(m::AbstractMathProgModel, ref::ConstraintReference) = throw(MethodError()) -Base.delete!(m::AbstractMathProgModel, refs::Vector{ConstraintReference}) = throw(MethodError()) """ - addconstraint!(m::AbstractMathProgModel, b, a_constridx, a_varidx, a_coef, Q_constridx, Q_vari, Q_varj, Q_coef, S::AbstractSet)::ConstraintReference{typeof(S)} + addconstraint!(m::AbstractMathProgModel, b, a_constridx, a_varidx, a_coef, Q_constridx, Q_vari, Q_varj, Q_coef, S::AbstractSet)::QuadraticConstraintReference{typeof(S)} -Add the constraint +Add the quadratic-in-set constraint ```math Ax + b + q(x) \\in S ``` -where ``A`` is a sparse vector specified in triplet form by +where ``A`` is a sparse matrix specified in triplet form by `a_constridx`, `a_varidx`, and `a_coef`; ``b`` is a vector; ``q(x)`` is a vector with component ``(q(x))_k`` defined to be ``\\frac{1}{2}x^TQ_kx`` where the symmetric matrix ``Q_k`` is defined by the triplets in `Q_vari`, `Q_varj`, @@ -53,7 +18,9 @@ where the symmetric matrix ``Q_k`` is defined by the triplets in `Q_vari`, `Q_va Duplicate indices in either ``A`` or a ``Q`` matrix are accepted and will be summed together. Off-diagonal entries of ``Q`` will be mirrored, so either the upper triangular or lower triangular entries of ``Q`` should be provided. If entries for both ``(i,j)`` and ``(j,i)`` are provided, these are considered duplicate terms. `a_varidx`, `Q_vari`, `Q_varj` should be collections of `VariableReference` objects. - addconstraint!(m::AbstractMathProgModel, b, a_varidx, a_coef, Q_vari, Q_varj, Q_coef, S::AbstractSet)::ConstraintReference{typeof(S)} + + + addconstraint!(m::AbstractMathProgModel, b, a_varidx, a_coef, Q_vari, Q_varj, Q_coef, S::AbstractSet)::QuadraticConstraintReference{typeof(S)} A specialized version of `addconstraint!` for one-dimensional sets. Add the constraint @@ -65,9 +32,31 @@ where ``a`` is a sparse vector specified in tuple form by the symmetric matrix ``Q`` is defined by the triplets in `Q_vari`, `Q_varj`, `Q_coef`; and the set ``S`` is defined by `S`. - addconstraint!(m::AbstractMathProgModel, varidx, S::AbstractSet)::ConstraintReference{typeof(S)} + addconstraint!(m::AbstractMathProgModel, b, a_constridx, a_varidx, a_coef, S::AbstractSet)::AffineConstraintReference{typeof(S)} + +Add the affine-in-set constraint +```math +Ax + b \\in S +``` +where ``A`` is a sparse matrix specified in triplet form by +`a_constridx`, `a_varidx`, and `a_coef`; ``b`` is a vector; and the set ``S`` is defined by `S`. + +Duplicate indices either ``A`` are accepted and will be summed together. + + addconstraint!(m::AbstractMathProgModel, b, a_varidx, a_coef, S::AbstractSet)::AffineConstraintReference{typeof(S)} + +A specialized version of `addconstraint!` for one-dimensional sets. +Add the constraint +```math +a^Tx + b \\in S +``` +where ``a`` is a sparse vector specified in tuple form by +`a_varidx`, and `a_coef`; ``b`` is a scalar; and the set ``S`` is defined by `S`. + + + addconstraint!(m::AbstractMathProgModel, varidx, S::AbstractSet)::VariablewiseConstraintReference{typeof(S)} -A specialized version of `addconstraint!` for constraints on subsets of variables. +A specialized version of `addconstraint!` for variablewise constraints. Add the constraint ```math x_{varidx} \\in S diff --git a/src/SolverInterface/references.jl b/src/SolverInterface/references.jl new file mode 100644 index 0000000..eb573ba --- /dev/null +++ b/src/SolverInterface/references.jl @@ -0,0 +1,96 @@ + + +""" + VariablewiseConstraintReference{T} + +A lightweight object used to reference variablewise constraints in a model. +The parameter `T` is the type of set constraint referenced. +""" +struct VariablewiseConstraintReference{T} + value::UInt64 +end + +""" + AffineConstraintReference{T} + +A lightweight object used to reference affine-in-set constraints in a model. +The parameter `T` is the type of set constraint referenced. +""" +struct AffineConstraintReference{T} + value::UInt64 +end + +""" + QuadraticConstraintReference{T} + +A lightweight object used to reference quadratic-in-set constraints in a model. +The parameter `T` is the type of set constraint referenced. +""" +struct QuadraticConstraintReference{T} + value::UInt64 +end + +const ConstraintReference = Union{VariablewiseConstraintReference,AffineConstraintReference,QuadraticConstraintReference} + +""" + candelete(m::AbstractMathProgModel, ref::ConstraintReference)::Bool + +Return a `Bool` indicating whether this constraint can be removed from the model `m`. +""" +candelete(m::AbstractMathProgModel, ref::ConstraintReference) = throw(MethodError()) + +""" + isvalid(m::AbstractMathProgModel, ref::ConstraintReference)::Bool + +Return a `Bool` indicating whether this reference is valid +for an active constraint in the model `m`. +""" +isvalid(m::AbstractMathProgModel, ref::ConstraintReference) = throw(MethodError()) + +""" + delete!(m::AbstractMathProgModel, ref::ConstraintReference) + +Delete the referenced constraint from the model. + + delete!(m::AbstractMathProgModel, refs::Vector{ConstraintReference}) + +Delete the referenced constraints in the vector `refs` from the model. +""" +Base.delete!(m::AbstractMathProgModel, ref::ConstraintReference) = throw(MethodError()) +Base.delete!(m::AbstractMathProgModel, refs::Vector{ConstraintReference}) = throw(MethodError()) + +""" + VariableReference + +A lightweight object used to reference variables in a model. +""" +struct VariableReference + value::UInt64 +end + +""" + candelete(m::AbstractMathProgModel, ref::VariableReference)::Bool + +Return a `Bool` indicating whether this variable can be removed from the model `m`. +""" +candelete(m::AbstractMathProgModel, ref::VariableReference) = throw(MethodError()) + +""" + isvalid(m::AbstractMathProgModel, ref::VariableReference)::Bool + +Return a `Bool` indicating whether this reference is valid +for an active variable in the model `m`. +""" +isvalid(m::AbstractMathProgModel, ref::VariableReference) = throw(MethodError()) + +""" + delete!(m::AbstractMathProgModel, ref::VariableReference) + +Delete the referenced variable from the model. + + delete!(m::AbstractMathProgModel, refs::Vector{VariableReference}) + +Delete the referenced variables in the vector `refs` from the model. +""" +Base.delete!(m::AbstractMathProgModel, ref::VariableReference) = throw(MethodError()) +Base.delete!(m::AbstractMathProgModel, refs::Vector{VariableReference}) = throw(MethodError()) diff --git a/src/SolverInterface/variables.jl b/src/SolverInterface/variables.jl index 8481a38..5fe13b6 100644 --- a/src/SolverInterface/variables.jl +++ b/src/SolverInterface/variables.jl @@ -1,43 +1,5 @@ -struct GenericVariableReference{T} - value::UInt64 -end -""" - VariableReference - -A lightweight object used to reference variables in a model. -""" -const VariableReference = GenericVariableReference{1} - -""" - candelete(m::AbstractMathProgModel, ref::VariableReference)::Bool - -Return a `Bool` indicating whether this variable can be removed from the model `m`. -""" -candelete(m::AbstractMathProgModel, ref::VariableReference) = throw(MethodError()) - -""" - isvalid(m::AbstractMathProgModel, ref::VariableReference)::Bool - -Return a `Bool` indicating whether this reference is valid -for an active variable in the model `m`. -""" -isvalid(m::AbstractMathProgModel, ref::VariableReference) = throw(MethodError()) - -""" - delete!(m::AbstractMathProgModel, ref::VariableReference) - -Delete the referenced variable from the model. - - delete!(m::AbstractMathProgModel, refs::Vector{VariableReference}) - -Delete the referenced variables in the vector `refs` from the model. -""" -Base.delete!(m::AbstractMathProgModel, ref::VariableReference) = throw(MethodError()) -Base.delete!(m::AbstractMathProgModel, refs::Vector{VariableReference}) = throw(MethodError()) - - """ addvariables!(m::AbstractMathProgModel, N::Int) From 1d6ef9e71dd37148135eb2d3eba922bc067dd833 Mon Sep 17 00:00:00 2001 From: Miles Lubin Date: Thu, 15 Jun 2017 17:40:52 -0400 Subject: [PATCH 49/83] document objectives --- docs/make.jl | 1 + docs/src/objectives.md | 10 ++++++++++ 2 files changed, 11 insertions(+) create mode 100644 docs/src/objectives.md diff --git a/docs/make.jl b/docs/make.jl index 0485beb..8675a90 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -9,6 +9,7 @@ makedocs( "Solver Interface" => [ "Basics" => "basics.md", "Variables" => "variables.md", + "Objectives" => "objectives.md", "Constraints" => "constraints.md", "Sets" => "sets.md", "Attributes" => "attributes.md", diff --git a/docs/src/objectives.md b/docs/src/objectives.md new file mode 100644 index 0000000..09b8896 --- /dev/null +++ b/docs/src/objectives.md @@ -0,0 +1,10 @@ +```@meta +CurrentModule = MathProgBase +``` + +How to add and set objectives. +```@docs +setobjective! +modifyobjective! +getobjective +``` From 840297092b719365c0a57705b4a9161447785248 Mon Sep 17 00:00:00 2001 From: odow Date: Thu, 15 Jun 2017 17:49:02 -0400 Subject: [PATCH 50/83] Modify sets --- docs/src/constraints.md | 3 ++- src/SolverInterface/constraints.jl | 14 ++++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/docs/src/constraints.md b/docs/src/constraints.md index 1d55777..47b47d1 100644 --- a/docs/src/constraints.md +++ b/docs/src/constraints.md @@ -2,7 +2,7 @@ CurrentModule = MathProgBase ``` -How to add constraints. +How to add and modify constraints. ```@docs VariablewiseConstraintReference AffineConstraintReference @@ -11,4 +11,5 @@ candelete(::AbstractMathProgModel,::ConstraintReference) isvalid(::AbstractMathProgModel,::ConstraintReference) delete!(::AbstractMathProgModel,::ConstraintReference) addconstraint! +modifyconstraint! ``` diff --git a/src/SolverInterface/constraints.jl b/src/SolverInterface/constraints.jl index 08411d7..cf05f16 100644 --- a/src/SolverInterface/constraints.jl +++ b/src/SolverInterface/constraints.jl @@ -116,5 +116,19 @@ and ``(j,i)`` are provided, these are considered duplicate terms. modifyconstraint!(m, c, v1, v2, 1.0) modifyconstraint!(m, c, [v1, v2], [v1, v1], [1.0, 2.0]) + +# Modify Set + + modifyconstraint!(m::AbstractMathProgModel, c::ConstraintReference{S}, set::S) + +Change the set of constraint `c` to the new set `set` which should be of the same +type as the original set. + +### Examples + +If `c` is a `ConstraintReference{Interval}` + + modifyconstraint!(m, c, Interval(0, 5)) + modifyconstraint!(m, c, NonPositive) # errors """ function modifyconstraint! end From 2427d591151a5765bf255f55e21d377f0a7ada82 Mon Sep 17 00:00:00 2001 From: Carleton Coffrin Date: Thu, 15 Jun 2017 23:23:06 -0400 Subject: [PATCH 51/83] Proposed NLP Interface (#183) * porting NLP interface docs to docstrings * adding nlp attribitutes, loadproblem -> loadnlp * adding type to sense in loadnlp * renaming Nonlinear.jl to nlp.jl --- docs/make.jl | 3 +- docs/src/nlp.md | 35 ++++ src/SolverInterface/Nonlinear.jl | 36 ---- src/SolverInterface/SolverInterface.jl | 2 +- src/SolverInterface/nlp.jl | 223 +++++++++++++++++++++++++ 5 files changed, 261 insertions(+), 38 deletions(-) create mode 100644 docs/src/nlp.md delete mode 100644 src/SolverInterface/Nonlinear.jl create mode 100644 src/SolverInterface/nlp.jl diff --git a/docs/make.jl b/docs/make.jl index 8675a90..d000b9a 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -14,7 +14,8 @@ makedocs( "Sets" => "sets.md", "Attributes" => "attributes.md", "Status Codes" => "statuscodes.md", - "Duals" => "duals.md"], + "Duals" => "duals.md", + "NLP" => "nlp.md"], "Choosing Solver" => "choosingsolver.md" ] ) diff --git a/docs/src/nlp.md b/docs/src/nlp.md new file mode 100644 index 0000000..ee3ddb1 --- /dev/null +++ b/docs/src/nlp.md @@ -0,0 +1,35 @@ +```@meta + CurrentModule = MathProgBase +``` + +# NonLinear Programming Interface (NLP) + + +## NLP Methods + +```@docs +loadnlp! +initialize +features_available +eval_f +eval_grad_f +jac_structure +hesslag_structure +eval_jac_g +eval_jac_prod +eval_jac_prod_t +eval_hesslag_prod +eval_hesslag +isobjlinear(::AbstractNLPEvaluator) +isobjquadratic(::AbstractNLPEvaluator) +isconstrlinear(::AbstractNLPEvaluator, i::Integer) +obj_expr +constr_expr +``` + +## NLP Attributes + +```@docs +ConstraintNLPDual +ConstraintNLPDualStart +``` diff --git a/src/SolverInterface/Nonlinear.jl b/src/SolverInterface/Nonlinear.jl deleted file mode 100644 index 92c817f..0000000 --- a/src/SolverInterface/Nonlinear.jl +++ /dev/null @@ -1,36 +0,0 @@ -# Methods for the Nonlinear interface - -abstract type AbstractNonlinearModel <: AbstractMathProgModel end -export AbstractNonlinearModel - -abstract type AbstractNLPEvaluator end -export AbstractNLPEvaluator - -# methods for AbstractNLPEvaluator -@define_interface begin - NonlinearModel - initialize - features_available - eval_f - eval_g - eval_grad_f - jac_structure - hesslag_structure - eval_jac_g - eval_jac_prod - eval_jac_prod_t - eval_hesslag_prod - eval_hesslag - isobjlinear - isobjquadratic - isconstrlinear - obj_expr - constr_expr -end - -# fallback options -isobjlinear(::AbstractNLPEvaluator) = false -isobjquadratic(::AbstractNLPEvaluator) = false -isconstrlinear(::AbstractNLPEvaluator, i::Integer) = false - -# getreducedcosts and getconstrduals already have stubs diff --git a/src/SolverInterface/SolverInterface.jl b/src/SolverInterface/SolverInterface.jl index 8ffec8b..b0467dc 100644 --- a/src/SolverInterface/SolverInterface.jl +++ b/src/SolverInterface/SolverInterface.jl @@ -95,10 +95,10 @@ include("constraints.jl") include("sets.jl") include("attributes.jl") include("objectives.jl") +include("nlp.jl") #include("LinearQuadratic.jl") #include("callbacks.jl") -#include("Nonlinear.jl") #include("Conic.jl") # Solver conversion routines diff --git a/src/SolverInterface/nlp.jl b/src/SolverInterface/nlp.jl new file mode 100644 index 0000000..1f16a24 --- /dev/null +++ b/src/SolverInterface/nlp.jl @@ -0,0 +1,223 @@ +# Methods for the Nonlinear interface + +abstract type AbstractNonlinearModel <: AbstractMathProgModel end +export AbstractNonlinearModel + +abstract type AbstractNLPEvaluator end +export AbstractNLPEvaluator + + +### NLP Attributes ### + +""" + ConstraintNLPDual(N) + ConstraintNLPDual() + +The assignment to the NLP constraint dual values in result `N`. If `N` is omitted, it is 1 by default. +""" +struct ConstraintNLPDual <: AbstractAttribute + N::Int +end +ConstraintNLPDual() = ConstraintNLPDual(1) + + +""" + ConstraintNLPDualStart() + +An initial assignment of the NLP constriant duals that the solver may use +to warm-start the solve. +""" +struct ConstraintNLPDualStart <: AbstractAttribute end + + +### methods for AbstractNLPEvaluator ### + +""" + +""" +function NonlinearModel end + + +""" + loadnlp!(m::AbstractNonlinearModel, numVar, numConstr, l, u, lb, ub, sense::OptimizationSense, d::AbstractNLPEvaluator) + +Loads the nonlinear programming problem into the model. The parameter `numVar` is the number of variables in the problem, `numConstr` is the number of constraints, `l` contains the variable lower bounds, `u` contains the variable upper bounds, `lb` contains the constraint lower bounds, and `ub` contains the constraint upper bounds. Sense contains the symbol `:Max` or `:Min`, indicating the direction of optimization. The final parameter `d` is an instance of an `AbstractNLPEvaluator`, described below, which may be queried for evaluating ``f`` and ``g`` and their corresponding derivatives. +""" +function loadnlp! end + + +""" + initialize(d::AbstractNLPEvaluator, requested_features::Vector{Symbol}) + +Must be called before any other methods. The vector `requested_features` +lists features requested by the solver. These may include `:Grad` for gradients +of ``f``, `:Jac` for explicit Jacobians of ``g``, `:JacVec` for +Jacobian-vector products, `:HessVe` for Hessian-vector +and Hessian-of-Lagrangian-vector products, `:Hess` for explicit Hessians and +Hessian-of-Lagrangians, and `:ExprGraph` for expression graphs. +""" +function initialize end + + +""" + features_available(d::AbstractNLPEvaluator) + +Returns the subset of features available for this problem instance, as a +list of symbols in the same format as in `initialize`. +""" +function features_available end + + +""" + eval_f(d::AbstractNLPEvaluator, x) + +Evaluate ``f(x)``, returning a scalar value. +""" +function eval_f end + + +""" + eval_g(d::AbstractNLPEvaluator, g, x) + +Evaluate ``g(x)``, storing the result in the vector `g` which +must be of the appropriate size. +""" +function eval_g end + + +""" + eval_grad_f(d::AbstractNLPEvaluator, g, x) + +Evaluate ``\\nabla f(x)`` as a dense vector, storing +the result in the vector `g` which must be of the appropriate size. +""" +function eval_grad_f end + + +""" + jac_structure(d::AbstractNLPEvaluator) + +Returns the sparsity structure of the Jacobian matrix, ``J_g(x) = \\left[ \\begin{array}{c} \\nabla g_1(x) \\\\ \\nabla g_2(x) \\\\ \\vdots \\\\ \\nabla g_m(x) \\end{array} \\right]`` where ``g_i`` is the ``i\\text{th}`` component of ``g``. The sparsity structure is assumed to be independent of the point ``x``. Returns a tuple ``(I,J)`` where ``I`` contains the row indices and ``J`` contains the column indices of each structurally nonzero element. These indices are not required to be sorted and can contain duplicates, in which case the solver should combine the corresponding elements by adding them together. +""" +function jac_structure end + + +""" + hesslag_structure(d::AbstractNLPEvaluator) + +Returns the sparsity structure of the Hessian-of-the-Lagrangian matrix +``\\nabla^2 f + \\sum_{i=1}^m \\nabla^2 g_i`` as a tuple ``(I,J)`` +where ``I`` contains the row indices and ``J`` contains the column indices of each +structurally nonzero element. These indices are not required to be sorted and can contain duplicates, in which case the solver should combine the corresponding elements by adding them together. Any mix of lower and upper-triangular indices is valid. +Elements ``(i,j)`` and ``(j,i)``, if both present, should be treated as duplicates. +""" +function hesslag_structure end + + +""" + eval_jac_g(d::AbstractNLPEvaluator, J, x) + +Evaluates the sparse Jacobian matrix ``J_g(x) = \\left[ \\begin{array}{c} \\nabla g_1(x) \\\\ \\nabla g_2(x) \\\\ \\vdots \\\\ \\nabla g_m(x) \\end{array} \\right]``. +The result is stored in the vector `J` in the same order as the indices returned +by `jac_structure`. +""" +function eval_jac_g end + + +""" + eval_jac_prod(d::AbstractNLPEvaluator, y, x, w) + +Computes the Jacobian-vector product ``J_g(x)w``, storing the result in the vector `y`. +""" +function eval_jac_prod end + + +""" + eval_jac_prod_t(d::AbstractNLPEvaluator, y, x, w) + +Computes the Jacobian-transpose-vector product ``J_g(x)^T w``, +storing the result in the vector `y`. + +""" +function eval_jac_prod_t end + + +""" + eval_hesslag_prod(d::AbstractNLPEvaluator, h, x, v, σ, μ) + +Given scalar weight ``σ`` and vector of constraint weights ``μ``, computes the Hessian-of-the-Lagrangian-vector product ``\\left( \\sigma \\nabla^2 f(x) + \\sum_{i=1}^m \\mu_i \\nabla^2 g_i(x) \\right)v``, +storing the result in the vector ``h``. +""" +function eval_hesslag_prod end + + +""" + eval_hesslag(d::AbstractNLPEvaluator, H, x, σ, μ) + +Given scalar weight `σ` and vector of constraint weights `μ`, +computes the sparse Hessian-of-the-Lagrangian matrix +``\\sigma \\nabla^2 f(x) + \\sum_{i=1}^m \\mu_i \\nabla^2 g_i(x)``, +storing the result in the vector `H` in the same order as the indices +returned by `hesslag_structure`. +""" +function eval_hesslag end + + +""" + obj_expr(d::AbstractNLPEvaluator) + +Returns an expression graph for the objective function as a standard Julia `Expr` +object. All sums and products are flattened out as simple `Expr(:+,...)` and +`Expr(:*,...)` objects. The symbol `x` is used as a placeholder for the +vector of decision variables. No other undefined symbols are permitted; +coefficients are embedded as explicit values. +For example, the expression +``x_1+\\sin(x_2/\\exp(x_3))`` would be represented as the Julia object +`:(x[1] + sin(x[2]/exp(x[3])))`. See the [Julia manual](http://docs.julialang.org/en/release-0.3/manual/metaprogramming/#expressions-and-eval) for more information +on the structure of `Expr` objects. There are currently no restrictions on +recognized functions; typically these will be built-in Julia functions like +`^`, `exp`, `log`, `cos`, `tan`, `sqrt`, etc., but modeling +interfaces may choose to extend these basic functions. +""" +function obj_expr end + + +""" + constr_expr(d::AbstractNLPEvaluator, i) + +Returns an expression graph for the ``i\\text{th}`` constraint in the same format as described above. The head of the expression is ``:comparison``, indicating the sense +of the constraint. The right-hand side of the comparison must be a constant; that is, +`:(x[1]^3 <= 1)` is allowed, while `:(1 <= x[1]^3)` is not valid. +Double-sided constraints are allowed, in which case both the lower bound and +upper bounds should be constants; for example, `:(-1 <= cos(x[1]) + sin(x[2]) <= 1)` is valid. +""" +function constr_expr end + + +### fallback options ### +""" + isobjlinear(::AbstractNLPEvaluator) + +`true` if the objective function is known to be linear, +`false` otherwise. +""" +isobjlinear(::AbstractNLPEvaluator) = false + + +""" + isobjquadratic(::AbstractNLPEvaluator) + +`true` if the objective function is known to be quadratic (convex or nonconvex), `false` otherwise. +""" +isobjquadratic(::AbstractNLPEvaluator) = false + + +""" + isconstrlinear(::AbstractNLPEvaluator, i::Integer) + +`true` if the ``i\text{th}`` constraint is known to be linear, `false` otherwise. +""" +isconstrlinear(::AbstractNLPEvaluator, i::Integer) = false + + + From 446c8db147b7ef9faa259e06def29d4aa8077528 Mon Sep 17 00:00:00 2001 From: Miles Lubin Date: Thu, 15 Jun 2017 23:24:49 -0400 Subject: [PATCH 52/83] temporarily disable tests --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index c689a0e..3c8f07b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -17,7 +17,7 @@ addons: script: - if [[ -a .git/shallow ]]; then git fetch --unshallow; fi - julia -e 'Pkg.clone(pwd())' - - julia -e 'Pkg.test("MathProgBase")' + #- julia -e 'Pkg.test("MathProgBase")' after_success: - julia -e 'Pkg.add("Documenter")' - julia -e 'cd(Pkg.dir("MathProgBase")); include(joinpath("docs", "make.jl"))' From f85eba93e42eb69576b21b4740d10801cdbf752f Mon Sep 17 00:00:00 2001 From: Miles Lubin Date: Thu, 15 Jun 2017 23:30:26 -0400 Subject: [PATCH 53/83] remove AbstractNonlinearModel --- src/SolverInterface/nlp.jl | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/SolverInterface/nlp.jl b/src/SolverInterface/nlp.jl index 1f16a24..2866b2a 100644 --- a/src/SolverInterface/nlp.jl +++ b/src/SolverInterface/nlp.jl @@ -1,8 +1,5 @@ # Methods for the Nonlinear interface -abstract type AbstractNonlinearModel <: AbstractMathProgModel end -export AbstractNonlinearModel - abstract type AbstractNLPEvaluator end export AbstractNLPEvaluator From 0cbe981302c12c5cccb947e0745e9c7a36a8af02 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Legat?= Date: Fri, 16 Jun 2017 14:32:01 +0200 Subject: [PATCH 54/83] Fix typos and color syntaxing (#185) --- src/HighLevelInterface/linprog.jl | 40 +++++++++++++++------------- src/HighLevelInterface/mixintprog.jl | 16 ++++++----- src/HighLevelInterface/quadprog.jl | 33 ++++++++++++----------- src/SolverInterface/attributes.jl | 10 ++++--- src/SolverInterface/constraints.jl | 33 ++++++++++++----------- src/SolverInterface/nlp.jl | 7 ++--- src/SolverInterface/objectives.jl | 18 ++++++++----- src/SolverInterface/references.jl | 2 -- src/SolverInterface/sets.jl | 2 -- src/SolverInterface/variables.jl | 5 +--- 10 files changed, 87 insertions(+), 79 deletions(-) diff --git a/src/HighLevelInterface/linprog.jl b/src/HighLevelInterface/linprog.jl index a0fb3f6..861cf42 100644 --- a/src/HighLevelInterface/linprog.jl +++ b/src/HighLevelInterface/linprog.jl @@ -197,7 +197,9 @@ A scalar is accepted for the ``l``, ``u``, ``rowlb``, and ``rowub`` arguments, i A variant usage of this function is to consider the linear programming problem in the following form, - linprog(c::InputVector, A::AbstractMatrix, sense::InputVector, b::InputVector, lb::InputVector, ub::InputVector, solver::AbstractMathProgSolver) +```julia +linprog(c::InputVector, A::AbstractMatrix, sense::InputVector, b::InputVector, lb::InputVector, ub::InputVector, solver::AbstractMathProgSolver) +``` ```math \\begin{align*} @@ -224,7 +226,9 @@ where: A shortened version is defined as:: - linprog(c, A, lb, ub, solver) = linprog(c, A, lb, ub, 0, Inf, solver) +```julia +linprog(c, A, lb, ub, solver) = linprog(c, A, lb, ub, 0, Inf, solver) +``` !!! note The function [`linprog`](@ref) calls two independent functions for building and solving the linear programming problem, namely [`buildlp`](@ref) and [`solvelp`](@ref). @@ -232,12 +236,12 @@ A shortened version is defined as:: The [`linprog`](@ref) function returns an instance of the type:: ```julia - type LinprogSolution - status - objval - sol - attrs - end +type LinprogSolution + status + objval + sol + attrs +end ``` where `status` is a termination status symbol, one of `:Optimal`, `:Infeasible`, `:Unbounded`, `:UserLimit` (iteration limit or timeout), `:Error` (and maybe others). @@ -256,7 +260,7 @@ If `status` is `:Infeasible`, the `attrs` member will contain an `infeasibilityr - `colbasis` -- optimal simplex basis statuses for the variables (columns) if available. Possible values are `:NonbasicAtLower`, `:NonbasicAtUpper`, `:Basic`, and `:Superbasic` (not yet implemented by any solvers) - `rowbasis` -- optimal simplex basis statuses for the constraints (rows) if available (not yet implemented by any solvers) -For example, we can solve the two-dimensional problem (see ``test/linprog.jl``): +For example, we can solve the two-dimensional problem (see `test/linprog.jl`): ```math \\begin{align*} @@ -267,15 +271,15 @@ For example, we can solve the two-dimensional problem (see ``test/linprog.jl``): ``` ```julia - using MathProgBase, Clp - - sol = linprog([-1,0],[2 1],'<',1.5, ClpSolver()) - if sol.status == :Optimal - println("Optimal objective value is \$(sol.objval)") - println("Optimal solution vector is: [\$(sol.sol[1]), \$(sol.sol[2])]") - else - println("Error: solution status \$(sol.status)") - end +using MathProgBase, Clp + +sol = linprog([-1,0],[2 1],'<',1.5, ClpSolver()) +if sol.status == :Optimal + println("Optimal objective value is \$(sol.objval)") + println("Optimal solution vector is: [\$(sol.sol[1]), \$(sol.sol[2])]") +else + println("Error: solution status \$(sol.status)") +end ``` """ diff --git a/src/HighLevelInterface/mixintprog.jl b/src/HighLevelInterface/mixintprog.jl index b5137c7..0ae4beb 100644 --- a/src/HighLevelInterface/mixintprog.jl +++ b/src/HighLevelInterface/mixintprog.jl @@ -29,12 +29,14 @@ A scalar is accepted for the ``sense``, ``b``, ``vartypes``, ``lb``, and ``ub`` The [`mixintprog`](@ref) function returns an instance of the type:: - type MixintprogSolution - status - objval - sol - attrs - end +```julia +type MixintprogSolution + status + objval + sol + attrs +end +``` where `status` takes the same values as with [`linprog`](@ref). @@ -61,7 +63,7 @@ We can solve a [binary knapsack problem](http://en.wikipedia.org/wiki/Knapsack_p with the following code ```julia - mixintprog(-[5.,3.,2.,7.,4.],[2. 8. 4. 2. 5.],'<',10,:Int,0,1,CbcSolver()) +mixintprog(-[5.,3.,2.,7.,4.],[2. 8. 4. 2. 5.],'<',10,:Int,0,1,CbcSolver()) ``` """ diff --git a/src/HighLevelInterface/quadprog.jl b/src/HighLevelInterface/quadprog.jl index b4ca08d..6a20cee 100644 --- a/src/HighLevelInterface/quadprog.jl +++ b/src/HighLevelInterface/quadprog.jl @@ -56,12 +56,14 @@ A scalar is accepted for the ``b``, ``sense``, ``l``, and ``u`` arguments, in wh The [`quadprog`](@ref) function returns an instance of the type:: - type QuadprogSolution - status - objval - sol - attrs - end +```julia +type QuadprogSolution + status + objval + sol + attrs +end +``` where `status` is a termination status symbol, one of `:Optimal`, `:Infeasible`, `:Unbounded`, `:UserLimit` (iteration limit or timeout), `:Error` (and maybe others). @@ -84,16 +86,15 @@ We can solve the three-dimensional QP (see `test/quadprog.jl`): ``` ```julia - - using MathProgBase, Ipopt - - sol = quadprog([0., 0., 0.],[2. 1. 0.; 1. 2. 1.; 0. 1. 2.],[1. 2. 3.; 1. 1. 0.],'>',[4., 1.],-Inf,Inf, IpoptSolver()) - if sol.status == :Optimal - println("Optimal objective value is \$(sol.objval)") - println("Optimal solution vector is: [\$(sol.sol[1]), \$(sol.sol[2]), \$(sol.sol[3])]") - else - println("Error: solution status \$(sol.status)") - end +using MathProgBase, Ipopt + +sol = quadprog([0., 0., 0.],[2. 1. 0.; 1. 2. 1.; 0. 1. 2.],[1. 2. 3.; 1. 1. 0.],'>',[4., 1.],-Inf,Inf, IpoptSolver()) +if sol.status == :Optimal + println("Optimal objective value is \$(sol.objval)") + println("Optimal solution vector is: [\$(sol.sol[1]), \$(sol.sol[2]), \$(sol.sol[3])]") +else + println("Error: solution status \$(sol.status)") +end ``` """ diff --git a/src/SolverInterface/attributes.jl b/src/SolverInterface/attributes.jl index 8f63346..d14333a 100644 --- a/src/SolverInterface/attributes.jl +++ b/src/SolverInterface/attributes.jl @@ -13,10 +13,12 @@ Return an attribute of the model `m` specified by attribute type `attr`. # Examples - getattribute(m, ObjectiveValue()) - getattribute(m, VariableResult(), ref) - getattribute(m, VariableResult(5), [ref1,ref2]) - getattribute(m, OtherAttribute("something specific to cplex")) +```julia +getattribute(m, ObjectiveValue()) +getattribute(m, VariableResult(), ref) +getattribute(m, VariableResult(5), [ref1,ref2]) +getattribute(m, OtherAttribute("something specific to cplex")) +``` """ function getattribute end diff --git a/src/SolverInterface/constraints.jl b/src/SolverInterface/constraints.jl index cf05f16..f60edaa 100644 --- a/src/SolverInterface/constraints.jl +++ b/src/SolverInterface/constraints.jl @@ -1,8 +1,3 @@ - - - - - """ addconstraint!(m::AbstractMathProgModel, b, a_constridx, a_varidx, a_coef, Q_constridx, Q_vari, Q_varj, Q_coef, S::AbstractSet)::QuadraticConstraintReference{typeof(S)} @@ -16,7 +11,7 @@ where ``A`` is a sparse matrix specified in triplet form by where the symmetric matrix ``Q_k`` is defined by the triplets in `Q_vari`, `Q_varj`, `Q_coef` for which `Q_constridx` equals `k`; and the set ``S`` is defined by `S`. -Duplicate indices in either ``A`` or a ``Q`` matrix are accepted and will be summed together. Off-diagonal entries of ``Q`` will be mirrored, so either the upper triangular or lower triangular entries of ``Q`` should be provided. If entries for both ``(i,j)`` and ``(j,i)`` are provided, these are considered duplicate terms. `a_varidx`, `Q_vari`, `Q_varj` should be collections of `VariableReference` objects. +Duplicate indices in either the ``A`` or the ``Q`` matrix are accepted and will be summed together. Off-diagonal entries of ``Q`` will be mirrored, so either the upper triangular or lower triangular entries of ``Q`` should be provided. If entries for both ``(i,j)`` and ``(j,i)`` are provided, these are considered duplicate terms. `a_varidx`, `Q_vari`, `Q_varj` should be collections of `VariableReference` objects. @@ -71,7 +66,7 @@ function addconstraint! end Modify elements of the `i`'th row of the constraint `c` depending on the arguments `args`. The `i`'th row will have the form ```math - a_i^T + b_i + \\frac{1}{2}x^TQ_ix \\in S + a_i^Tx + b_i + \\frac{1}{2}x^TQ_ix \\in S ``` There are three cases. @@ -83,11 +78,13 @@ Set the constant term of the `i`'th row in the constraint `c` to `b`. ### Examples - modifyconstraint!(m, c, 1, 1.0) +```julia +modifyconstraint!(m, c, 1, 1.0) +``` # Modify Linear term -modifyconstraint!(m::AbstractMathProgModel, c::ConstraintReference, i::Int, a_varidx, a_coef) + modifyconstraint!(m::AbstractMathProgModel, c::ConstraintReference, i::Int, a_varidx, a_coef) Set elements given by `a_varidx` in the linear term of the `i`'th element in the constraint `c` to `a_coef`. Either `a_varidx` and `a_coef` are both singletons, @@ -97,8 +94,10 @@ The behaviour of duplicate entries in `a_varidx` is undefined. ### Examples - modifyconstraint!(m, c, v, 1.0) - modifyconstraint!(m, c, [v1, v2], [1.0, 2.0]) +```julia +modifyconstraint!(m, c, v, 1.0) +modifyconstraint!(m, c, [v1, v2], [1.0, 2.0]) +``` # Modify Quadratic term @@ -114,8 +113,10 @@ and ``(j,i)`` are provided, these are considered duplicate terms. ### Examples - modifyconstraint!(m, c, v1, v2, 1.0) - modifyconstraint!(m, c, [v1, v2], [v1, v1], [1.0, 2.0]) +```julia +modifyconstraint!(m, c, v1, v2, 1.0) +modifyconstraint!(m, c, [v1, v2], [v1, v1], [1.0, 2.0]) +``` # Modify Set @@ -128,7 +129,9 @@ type as the original set. If `c` is a `ConstraintReference{Interval}` - modifyconstraint!(m, c, Interval(0, 5)) - modifyconstraint!(m, c, NonPositive) # errors +```julia +modifyconstraint!(m, c, Interval(0, 5)) +modifyconstraint!(m, c, NonPositive) # errors +``` """ function modifyconstraint! end diff --git a/src/SolverInterface/nlp.jl b/src/SolverInterface/nlp.jl index 2866b2a..b604135 100644 --- a/src/SolverInterface/nlp.jl +++ b/src/SolverInterface/nlp.jl @@ -182,7 +182,7 @@ function obj_expr end """ constr_expr(d::AbstractNLPEvaluator, i) -Returns an expression graph for the ``i\\text{th}`` constraint in the same format as described above. The head of the expression is ``:comparison``, indicating the sense +Returns an expression graph for the ``i^{\\text{th}}`` constraint in the same format as described above. The head of the expression is ``:comparison``, indicating the sense of the constraint. The right-hand side of the comparison must be a constant; that is, `:(x[1]^3 <= 1)` is allowed, while `:(1 <= x[1]^3)` is not valid. Double-sided constraints are allowed, in which case both the lower bound and @@ -212,9 +212,6 @@ isobjquadratic(::AbstractNLPEvaluator) = false """ isconstrlinear(::AbstractNLPEvaluator, i::Integer) -`true` if the ``i\text{th}`` constraint is known to be linear, `false` otherwise. +`true` if the ``i^{\\text{th}}`` constraint is known to be linear, `false` otherwise. """ isconstrlinear(::AbstractNLPEvaluator, i::Integer) = false - - - diff --git a/src/SolverInterface/objectives.jl b/src/SolverInterface/objectives.jl index 4f16631..6102160 100644 --- a/src/SolverInterface/objectives.jl +++ b/src/SolverInterface/objectives.jl @@ -9,7 +9,7 @@ where ``a`` is a sparse vector specified in tuple form by `a_varidx`, and `a_coef`; ``b`` is a scalar; and the symmetric matrix ``Q`` is defined by the triplets in `Q_vari`, `Q_varj`, `Q_coef`. -Duplicate indices in either ``A`` or a ``Q`` matrix are accepted and will be +Duplicate indices in either the ``a`` vector or the ``Q`` matrix are accepted and will be summed together. Off-diagonal entries of ``Q`` will be mirrored, so either the upper triangular or lower triangular entries of ``Q`` should be provided. If entries for both ``(i,j)`` and ``(j,i)`` are provided, these are considered @@ -36,7 +36,9 @@ Set the constant term of the `i`'th row objective to `b`. ### Examples - modifyobjective!(m, 1, 1.0) +```julia +modifyobjective!(m, 1, 1.0) +``` # Modify Linear term @@ -50,8 +52,10 @@ The behaviour of duplicate entries in `a_varidx` is undefined. ### Examples - modifyobjective!(m, 1, v, 1.0) - modifyobjective!(m, 1, [v1, v2], [1.0, 2.0]) +```julia +modifyobjective!(m, 1, v, 1.0) +modifyobjective!(m, 1, [v1, v2], [1.0, 2.0]) +``` # Modify Quadratic term @@ -66,8 +70,10 @@ and ``(j,i)`` are provided, these are considered duplicate terms. ### Examples - modifyobjective!(m, 1, v1, v2, 1.0) - modifyobjective!(m, 1, [v1, v2], [v1, v1], [1.0, 2.0]) +```julia +modifyobjective!(m, 1, v1, v2, 1.0) +modifyobjective!(m, 1, [v1, v2], [v1, v1], [1.0, 2.0]) +``` """ function modifyobjective! end diff --git a/src/SolverInterface/references.jl b/src/SolverInterface/references.jl index eb573ba..b4b6b02 100644 --- a/src/SolverInterface/references.jl +++ b/src/SolverInterface/references.jl @@ -1,5 +1,3 @@ - - """ VariablewiseConstraintReference{T} diff --git a/src/SolverInterface/sets.jl b/src/SolverInterface/sets.jl index b2d71d9..484cd59 100644 --- a/src/SolverInterface/sets.jl +++ b/src/SolverInterface/sets.jl @@ -1,5 +1,3 @@ - - """ AbstractSet diff --git a/src/SolverInterface/variables.jl b/src/SolverInterface/variables.jl index 5fe13b6..6f7a7a2 100644 --- a/src/SolverInterface/variables.jl +++ b/src/SolverInterface/variables.jl @@ -1,5 +1,3 @@ - - """ addvariables!(m::AbstractMathProgModel, N::Int) @@ -11,7 +9,6 @@ function addvariables! end """ addvariable!(m::AbstractMathProgModel, N::Int) -Add a scalar variable to the model, returning a vector of variable -references. +Add a scalar variable to the model, returning variable reference. """ function addvariable! end From 63934092129c3547f8537cb18f26fa8479aebd10 Mon Sep 17 00:00:00 2001 From: Miles Lubin Date: Fri, 16 Jun 2017 09:29:33 -0400 Subject: [PATCH 55/83] fix addvariable --- src/SolverInterface/variables.jl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/SolverInterface/variables.jl b/src/SolverInterface/variables.jl index 6f7a7a2..a5d1c3a 100644 --- a/src/SolverInterface/variables.jl +++ b/src/SolverInterface/variables.jl @@ -1,5 +1,5 @@ """ - addvariables!(m::AbstractMathProgModel, N::Int) + addvariables!(m::AbstractMathProgModel, N::Int)::Vector{VariableReference} Add `N` scalar variables to the model, returning a vector of variable references. @@ -7,8 +7,8 @@ references. function addvariables! end """ - addvariable!(m::AbstractMathProgModel, N::Int) + addvariable!(m::AbstractMathProgModel)::VariableReference -Add a scalar variable to the model, returning variable reference. +Add a scalar variable to the model, returning a variable reference. """ function addvariable! end From 95134740405a15acaa1ff7612b62e6e9a971759c Mon Sep 17 00:00:00 2001 From: Miles Lubin Date: Fri, 16 Jun 2017 14:04:04 -0400 Subject: [PATCH 56/83] update intro --- docs/src/index.md | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/docs/src/index.md b/docs/src/index.md index 267db76..7efc762 100644 --- a/docs/src/index.md +++ b/docs/src/index.md @@ -1,7 +1,3 @@ # MathProgBase -Solver-independent functions and low-level interfaces for Mathematical Programming - -[MathProgBase.jl](https://github.com/JuliaOpt/MathProgBase.jl) provides high-level one-shot functions for linear and mixed-integer programming, as well as a solver-independent low-level interface for implementing advanced techniques that require efficiently solving a sequence of linear programming problems. - -To use MathProgBase, an external solver must be installed. See [Choosing Solvers](@ref). +[MathProgBase.jl](https://github.com/JuliaOpt/MathProgBase.jl) is a standarized API for Mathematical Optimization solvers. [JuMP](https://github.com/JuliaOpt/JuMP.jl) uses MathProgBase as a solver-independent low-level backend, but MathProgBase may be used freely without JuMP. In addition to the low-level API, MathProgBase provides one-shot functions for linear, mixed-integer, and quadratic optimiztion problems. From d8cc31464d79eaaa9aec04700c7fdb3d51f26e43 Mon Sep 17 00:00:00 2001 From: Miles Lubin Date: Fri, 16 Jun 2017 14:11:08 -0400 Subject: [PATCH 57/83] rename attributes for constraint support --- docs/src/attributes.md | 6 +++--- src/SolverInterface/attributes.jl | 17 ++++++++--------- 2 files changed, 11 insertions(+), 12 deletions(-) diff --git a/docs/src/attributes.md b/docs/src/attributes.md index a0cccba..b66b7c3 100644 --- a/docs/src/attributes.md +++ b/docs/src/attributes.md @@ -27,9 +27,9 @@ RawSolver ResultCount VariableCount ConstraintCount -SupportsVariablesInSet -SupportsAffineInSet -SupportsQuadraticInSet +SupportsVariablewiseConstraint +SupportsAffineConstraint +SupportsQuadraticConstraint ``` ## Variable Attributes diff --git a/src/SolverInterface/attributes.jl b/src/SolverInterface/attributes.jl index d14333a..bd6a263 100644 --- a/src/SolverInterface/attributes.jl +++ b/src/SolverInterface/attributes.jl @@ -158,32 +158,31 @@ The number of constraints of type T in the model. struct ConstraintCount{T} <: AbstractAttribute end """ - SupportsVariablesInSet{T}() + SupportsVariablewiseConstraint{T}() A `Bool` indicating whether the solver or model supports -a constraint of type ``x_{varidx} \\in S`` where ``S`` -is a set of type `T` and ``varidx`` indicates any subset -of the variables. +a variablewise constraint in the set ``S`` which +is a set of type `T`. """ -struct SupportsVariablesInSet{T} <: AbstractAttribute end +struct SupportsVariablewiseConstraint{T} <: AbstractAttribute end """ - SupportsAffineInSet{T}() + SupportsAffineConstraint{T}() A `Bool` indicating whether the solver or model supports a constraint of of the form "affine expression" in ``S`` where ``S`` is a set of type `T`. """ -struct SupportsAffineInSet{T} <: AbstractAttribute end +struct SupportsAffineConstraint{T} <: AbstractAttribute end """ - SupportsQuadraticInSet{T}() + SupportsQuadraticConstraint{T}() A `Bool` indicating whether the solver or model supports a constraint of of the form "quadratic expression" in ``S`` where ``S`` is a set of type `T`. """ -struct SupportsQuadraticInSet{T} <: AbstractAttribute end +struct SupportsQuadraticConstraint{T} <: AbstractAttribute end From 4909aef4dae71430476edbf74daa221357e78da0 Mon Sep 17 00:00:00 2001 From: Miles Lubin Date: Fri, 16 Jun 2017 14:13:50 -0400 Subject: [PATCH 58/83] spellcheck --- docs/src/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/src/index.md b/docs/src/index.md index 7efc762..cabee06 100644 --- a/docs/src/index.md +++ b/docs/src/index.md @@ -1,3 +1,3 @@ # MathProgBase -[MathProgBase.jl](https://github.com/JuliaOpt/MathProgBase.jl) is a standarized API for Mathematical Optimization solvers. [JuMP](https://github.com/JuliaOpt/JuMP.jl) uses MathProgBase as a solver-independent low-level backend, but MathProgBase may be used freely without JuMP. In addition to the low-level API, MathProgBase provides one-shot functions for linear, mixed-integer, and quadratic optimiztion problems. +[MathProgBase.jl](https://github.com/JuliaOpt/MathProgBase.jl) is a standardized API for Mathematical Optimization solvers. [JuMP](https://github.com/JuliaOpt/JuMP.jl) uses MathProgBase as a solver-independent low-level backend, but MathProgBase may be used freely without JuMP. In addition to the low-level API, MathProgBase provides one-shot functions for linear, mixed-integer, and quadratic optimization problems. From b7e35bf47672234825562c1c7acc2f9f1bd4fff5 Mon Sep 17 00:00:00 2001 From: Miles Lubin Date: Fri, 16 Jun 2017 14:16:26 -0400 Subject: [PATCH 59/83] warn on high-level docs --- docs/src/highlevel.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/src/highlevel.md b/docs/src/highlevel.md index 21deb66..c69c4a0 100644 --- a/docs/src/highlevel.md +++ b/docs/src/highlevel.md @@ -2,6 +2,8 @@ CurrentModule = MathProgBase ``` +**These docs are out of date. We need to update the high-level interfaces for new statuses.** + ## Linear Programming ```@docs From cd7143936daacdc3e59829dbe5a9b1b3c9026b6e Mon Sep 17 00:00:00 2001 From: Miles Lubin Date: Fri, 16 Jun 2017 14:39:35 -0400 Subject: [PATCH 60/83] define SOC --- docs/src/sets.md | 3 +++ src/SolverInterface/sets.jl | 18 +++++++++++++++++- 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/docs/src/sets.md b/docs/src/sets.md index b11ae0d..00fd536 100644 --- a/docs/src/sets.md +++ b/docs/src/sets.md @@ -9,6 +9,9 @@ NonNegative NonPositive Zero Interval +SecondOrderCone Integers Binaries +SOS1 +SOS2 ``` diff --git a/src/SolverInterface/sets.jl b/src/SolverInterface/sets.jl index 484cd59..160b289 100644 --- a/src/SolverInterface/sets.jl +++ b/src/SolverInterface/sets.jl @@ -46,6 +46,22 @@ end dimension(s::Interval) = length(s.lower) +""" + SecondOrderCone(n) + +The second-order cone or the Lorenz cone of dimension `n` +defined as +```math +\\{ (t,x) \\in \\mathbb{R}^n : t \\ge ||x||_2 \\}. +``` +""" +struct SecondOrderCone <: AbstractSet + dim::Int +end + +#ExponentialCone +#PositiveSemidefiniteCone + """ Integers(n) @@ -65,7 +81,7 @@ struct Binaries <: AbstractSet end -dimension(s::Union{NonNegative,NonPositive,Zero,Integers,Binaries}) = s.dim +dimension(s::Union{NonNegative,NonPositive,Zero,SecondOrderCone,Integers,Binaries}) = s.dim """ SOS1(weights::Vector{T}) where T From 48c57360fda02c31803d385617e2d740706b40e9 Mon Sep 17 00:00:00 2001 From: Miles Lubin Date: Fri, 16 Jun 2017 14:40:05 -0400 Subject: [PATCH 61/83] lighten load on travis --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 3c8f07b..3b0f5b6 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,10 +1,10 @@ language: julia os: - linux - - osx +# - osx julia: - 0.6 - - nightly +# - nightly notifications: email: false sudo: false From ac06eba71f075d1c2fb751734645d671a374767a Mon Sep 17 00:00:00 2001 From: Miles Lubin Date: Fri, 16 Jun 2017 16:02:00 -0400 Subject: [PATCH 62/83] clarify variable references, not indices --- src/SolverInterface/constraints.jl | 32 +++++++++++++++--------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/src/SolverInterface/constraints.jl b/src/SolverInterface/constraints.jl index f60edaa..0d5b0ef 100644 --- a/src/SolverInterface/constraints.jl +++ b/src/SolverInterface/constraints.jl @@ -1,21 +1,21 @@ """ - addconstraint!(m::AbstractMathProgModel, b, a_constridx, a_varidx, a_coef, Q_constridx, Q_vari, Q_varj, Q_coef, S::AbstractSet)::QuadraticConstraintReference{typeof(S)} + addconstraint!(m::AbstractMathProgModel, b, a_constridx, a_varref::Vector{VariableReference}, a_coef, Q_constridx, Q_vari::Vector{VariableReference}, Q_varj::Vector{VariableReference}, Q_coef, S::AbstractSet)::QuadraticConstraintReference{typeof(S)} Add the quadratic-in-set constraint ```math Ax + b + q(x) \\in S ``` where ``A`` is a sparse matrix specified in triplet form by -`a_constridx`, `a_varidx`, and `a_coef`; ``b`` is a vector; +`a_constridx`, `a_varref`, and `a_coef`; ``b`` is a vector; ``q(x)`` is a vector with component ``(q(x))_k`` defined to be ``\\frac{1}{2}x^TQ_kx`` where the symmetric matrix ``Q_k`` is defined by the triplets in `Q_vari`, `Q_varj`, `Q_coef` for which `Q_constridx` equals `k`; and the set ``S`` is defined by `S`. -Duplicate indices in either the ``A`` or the ``Q`` matrix are accepted and will be summed together. Off-diagonal entries of ``Q`` will be mirrored, so either the upper triangular or lower triangular entries of ``Q`` should be provided. If entries for both ``(i,j)`` and ``(j,i)`` are provided, these are considered duplicate terms. `a_varidx`, `Q_vari`, `Q_varj` should be collections of `VariableReference` objects. +Duplicate indices in either the ``A`` or the ``Q`` matrix are accepted and will be summed together. Off-diagonal entries of ``Q`` will be mirrored, so either the upper triangular or lower triangular entries of ``Q`` should be provided. If entries for both ``(i,j)`` and ``(j,i)`` are provided, these are considered duplicate terms. `a_varref`, `Q_vari`, `Q_varj` should be collections of `VariableReference` objects. - addconstraint!(m::AbstractMathProgModel, b, a_varidx, a_coef, Q_vari, Q_varj, Q_coef, S::AbstractSet)::QuadraticConstraintReference{typeof(S)} + addconstraint!(m::AbstractMathProgModel, b, a_varref::Vector{VariableReference}, a_coef, Q_vari::Vector{VariableReference}, Q_varj::Vector{VariableReference}, Q_coef, S::AbstractSet)::QuadraticConstraintReference{typeof(S)} A specialized version of `addconstraint!` for one-dimensional sets. Add the constraint @@ -23,22 +23,22 @@ Add the constraint a^Tx + b + \\frac{1}{2}x^TQx \\in S ``` where ``a`` is a sparse vector specified in tuple form by -`a_varidx`, and `a_coef`; ``b`` is a scalar; +`a_varref`, and `a_coef`; ``b`` is a scalar; the symmetric matrix ``Q`` is defined by the triplets in `Q_vari`, `Q_varj`, `Q_coef`; and the set ``S`` is defined by `S`. - addconstraint!(m::AbstractMathProgModel, b, a_constridx, a_varidx, a_coef, S::AbstractSet)::AffineConstraintReference{typeof(S)} + addconstraint!(m::AbstractMathProgModel, b, a_constridx, a_varref::Vector{VariableReference}, a_coef, S::AbstractSet)::AffineConstraintReference{typeof(S)} Add the affine-in-set constraint ```math Ax + b \\in S ``` where ``A`` is a sparse matrix specified in triplet form by -`a_constridx`, `a_varidx`, and `a_coef`; ``b`` is a vector; and the set ``S`` is defined by `S`. +`a_constridx`, `a_varref`, and `a_coef`; ``b`` is a vector; and the set ``S`` is defined by `S`. Duplicate indices either ``A`` are accepted and will be summed together. - addconstraint!(m::AbstractMathProgModel, b, a_varidx, a_coef, S::AbstractSet)::AffineConstraintReference{typeof(S)} + addconstraint!(m::AbstractMathProgModel, b, a_varref::Vector{VariableReference}, a_coef, S::AbstractSet)::AffineConstraintReference{typeof(S)} A specialized version of `addconstraint!` for one-dimensional sets. Add the constraint @@ -46,17 +46,17 @@ Add the constraint a^Tx + b \\in S ``` where ``a`` is a sparse vector specified in tuple form by -`a_varidx`, and `a_coef`; ``b`` is a scalar; and the set ``S`` is defined by `S`. +`a_varref`, and `a_coef`; ``b`` is a scalar; and the set ``S`` is defined by `S`. - addconstraint!(m::AbstractMathProgModel, varidx, S::AbstractSet)::VariablewiseConstraintReference{typeof(S)} + addconstraint!(m::AbstractMathProgModel, varref::Vector{VariableReference}, S::AbstractSet)::VariablewiseConstraintReference{typeof(S)} A specialized version of `addconstraint!` for variablewise constraints. Add the constraint ```math -x_{varidx} \\in S +x_{varref} \\in S ``` -where `varidx` specifies the indices of the subvector of `x`. +where `varref` is a vector of variable references to specifiy the subset of the subvector of `x`. """ function addconstraint! end @@ -84,13 +84,13 @@ modifyconstraint!(m, c, 1, 1.0) # Modify Linear term - modifyconstraint!(m::AbstractMathProgModel, c::ConstraintReference, i::Int, a_varidx, a_coef) + modifyconstraint!(m::AbstractMathProgModel, c::ConstraintReference, i::Int, a_varref::Vector{VariableReference}, a_coef) -Set elements given by `a_varidx` in the linear term of the `i`'th element in the -constraint `c` to `a_coef`. Either `a_varidx` and `a_coef` are both singletons, +Set elements given by `a_varref` in the linear term of the `i`'th element in the +constraint `c` to `a_coef`. Either `a_varref` and `a_coef` are both singletons, or they should be collections with equal length. -The behaviour of duplicate entries in `a_varidx` is undefined. +The behaviour of duplicate entries in `a_varref` is undefined. ### Examples From 87e61f202504d7aef7718891219c42e1c5eb050e Mon Sep 17 00:00:00 2001 From: Miles Lubin Date: Fri, 16 Jun 2017 16:08:26 -0400 Subject: [PATCH 63/83] move attributes out of status code list --- docs/src/attributes.md | 5 +++++ docs/src/statuscodes.md | 8 +++----- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/docs/src/attributes.md b/docs/src/attributes.md index b66b7c3..c9c50cf 100644 --- a/docs/src/attributes.md +++ b/docs/src/attributes.md @@ -30,6 +30,9 @@ ConstraintCount SupportsVariablewiseConstraint SupportsAffineConstraint SupportsQuadraticConstraint +TerminationStatus +PrimalStatus +DualStatus ``` ## Variable Attributes @@ -45,6 +48,7 @@ VariableUpperBound VariablePrimal VariableLowerBoundDual VariableUpperBoundDual +VariableBasisStatus ``` ## Constraint Attributes @@ -56,6 +60,7 @@ ConstraintPrimalStart ConstraintDualStart ConstraintPrimal ConstraintDual +ConstraintBasisStatus ``` diff --git a/docs/src/statuscodes.md b/docs/src/statuscodes.md index 3f8af99..5c9efa3 100644 --- a/docs/src/statuscodes.md +++ b/docs/src/statuscodes.md @@ -8,7 +8,6 @@ CurrentModule = MathProgBase The `TerminationStatus` attribute is meant to explain the reason why the solver stopped executing. The value of the attribute is of type `TerminationStatusCode`. ```@docs -TerminationStatus TerminationStatusCode ``` @@ -17,12 +16,11 @@ TerminationStatusCode The `PrimalStatus` and `DualStatus` attributes are meant to explain how to interpret the result returned by the solver. The value of the attributes are of type `ResultStatusCode`. ```@docs -PrimalStatus -DualStatus ResultStatusCode ``` ## Basis Status -TODO: attributes and status codes for LP basis status - +```@docs +BasisStatusCode +``` From 0e1a103cf3e8a6a3d22e2fd5aab431164a17790d Mon Sep 17 00:00:00 2001 From: Oscar Dowson Date: Fri, 16 Jun 2017 16:09:18 -0400 Subject: [PATCH 64/83] column generation (#189) --- src/SolverInterface/variables.jl | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/SolverInterface/variables.jl b/src/SolverInterface/variables.jl index a5d1c3a..384ad55 100644 --- a/src/SolverInterface/variables.jl +++ b/src/SolverInterface/variables.jl @@ -10,5 +10,22 @@ function addvariables! end addvariable!(m::AbstractMathProgModel)::VariableReference Add a scalar variable to the model, returning a variable reference. + +In addition, there is a special case for adding variables to existing linear problems. + + addvariable!(m::AbstractMathProgModel, + cref::Vector{Union{ + AffineConstraintRef{NonPositive}, + AffineConstraintRef{NonNegative}, + AffineConstraintRef{Zero}, + AffineConstraintRef{Interval} + }}, + coefs)::VariableReference + +Add a variable with coefficients specified by `coefs` in the existing affine +constraints given by the constraint references `cref`. If you want to add a +variable with coefficients in a constraint that is not listed here (such as a +quadratic term, or in the SOC), use `addvariable!(m)` and then +`modifyconstraint!` instead. """ function addvariable! end From 3308af5d7a2cbcd896e347736e33ef54168c55d0 Mon Sep 17 00:00:00 2001 From: Carleton Coffrin Date: Fri, 16 Jun 2017 16:22:35 -0400 Subject: [PATCH 65/83] preliminary migration of nlp tests (#187) --- test/nlp.jl | 240 ++++++++++++++++++++++++++++------------------- test/runtests.jl | 2 + 2 files changed, 148 insertions(+), 94 deletions(-) diff --git a/test/nlp.jl b/test/nlp.jl index bf7d3fd..724cde4 100644 --- a/test/nlp.jl +++ b/test/nlp.jl @@ -1,9 +1,10 @@ using Base.Test using MathProgBase + # Here the type represents the complete instance, but it # could also store instance data. -type HS071 <: MathProgBase.AbstractNLPEvaluator +type HS071 <: MPB.AbstractNLPEvaluator end # hs071 @@ -14,7 +15,7 @@ end # Start at (1,5,5,1) # End at (1.000..., 4.743..., 3.821..., 1.379...) -function MathProgBase.initialize(d::HS071, requested_features::Vector{Symbol}) +function MPB.initialize(d::HS071, requested_features::Vector{Symbol}) for feat in requested_features if !(feat in [:Grad, :Jac, :Hess]) error("Unsupported feature $feat") @@ -24,28 +25,28 @@ function MathProgBase.initialize(d::HS071, requested_features::Vector{Symbol}) end end -MathProgBase.features_available(d::HS071) = [:Grad, :Jac, :Hess] +MPB.features_available(d::HS071) = [:Grad, :Jac, :Hess] -MathProgBase.eval_f(d::HS071, x) = x[1] * x[4] * (x[1] + x[2] + x[3]) + x[3] +MPB.eval_f(d::HS071, x) = x[1] * x[4] * (x[1] + x[2] + x[3]) + x[3] -function MathProgBase.eval_g(d::HS071, g, x) +function MPB.eval_g(d::HS071, g, x) g[1] = x[1] * x[2] * x[3] * x[4] g[2] = x[1]^2 + x[2]^2 + x[3]^2 + x[4]^2 end -function MathProgBase.eval_grad_f(d::HS071, grad_f, x) +function MPB.eval_grad_f(d::HS071, grad_f, x) grad_f[1] = x[1] * x[4] + x[4] * (x[1] + x[2] + x[3]) grad_f[2] = x[1] * x[4] grad_f[3] = x[1] * x[4] + 1 grad_f[4] = x[1] * (x[1] + x[2] + x[3]) end -MathProgBase.jac_structure(d::HS071) = [1,1,1,1,2,2,2,2],[1,2,3,4,1,2,3,4] +MPB.jac_structure(d::HS071) = [1,1,1,1,2,2,2,2],[1,2,3,4,1,2,3,4] # lower triangle only -MathProgBase.hesslag_structure(d::HS071) = [1,2,2,3,3,3,4,4,4,4],[1,1,2,1,2,3,1,2,3,4] +MPB.hesslag_structure(d::HS071) = [1,2,2,3,3,3,4,4,4,4],[1,1,2,1,2,3,1,2,3,4] -function MathProgBase.eval_jac_g(d::HS071, J, x) +function MPB.eval_jac_g(d::HS071, J, x) # Constraint (row) 1 J[1] = x[2]*x[3]*x[4] # 1,1 J[2] = x[1]*x[3]*x[4] # 1,2 @@ -58,7 +59,7 @@ function MathProgBase.eval_jac_g(d::HS071, J, x) J[8] = 2*x[4] # 2,4 end -function MathProgBase.eval_hesslag(d::HS071, H, x, σ, μ) +function MPB.eval_hesslag(d::HS071, H, x, σ, μ) # Again, only lower left triangle # Objective H[1] = σ * (2*x[4]) # 1,1 @@ -90,35 +91,48 @@ end function nlptest(solver) @testset "Testing NLP with $solver" begin - m = MathProgBase.NonlinearModel(solver) + m = MPB.NLPModel(solver) l = [1,1,1,1] u = [5,5,5,5] lb = [25, 40] ub = [Inf, 40] - MathProgBase.loadproblem!(m, 4, 2, l, u, lb, ub, :Min, HS071()) - MathProgBase.setwarmstart!(m,[1,5,5,1]) + vrefs = MPB.loadnlp!(m, 4, 2, l, u, lb, ub, MPB.MinSense, HS071()) + MPB.setattribute!(m, MPB.VariablePrimalStart(), vrefs, [1,5,5,1]) + + MPB.optimize!(m) + + termination_status = MPB.getattribute(m, MPB.TerminationStatus()) + @test termination_status == MPB.Success + + primal_status = MPB.getattribute(m, MPB.PrimalStatus()) + @test primal_status == MPB.FeasiblePoint - MathProgBase.optimize!(m) - stat = MathProgBase.status(m) + primal_sol = MPB.getattribute(m, MPB.VariablePrimal(), vrefs) + + @test isapprox(primal_sol[1], 1.0000000000000000, atol=1e-5) + @test isapprox(primal_sol[2], 4.7429996418092970, atol=1e-5) + @test isapprox(primal_sol[3], 3.8211499817883077, atol=1e-5) + @test isapprox(primal_sol[4], 1.3794082897556983, atol=1e-5) + + obj_val = MPB.getattribute(m, MPB.ObjectiveValue()) + @test isapprox(obj_val, 17.014017145179164, atol=1e-5) - @test stat == :Optimal - x = MathProgBase.getsolution(m) - @test isapprox(x[1], 1.0000000000000000, atol=1e-5) - @test isapprox(x[2], 4.7429996418092970, atol=1e-5) - @test isapprox(x[3], 3.8211499817883077, atol=1e-5) - @test isapprox(x[4], 1.3794082897556983, atol=1e-5) - @test isapprox(MathProgBase.getobjval(m), 17.014017145179164, atol=1e-5) # Test that a second call to optimize! works - MathProgBase.setwarmstart!(m,[1,5,5,1]) - MathProgBase.optimize!(m) - stat = MathProgBase.status(m) - @test stat == :Optimal + MPB.setattribute!(m, MPB.VariablePrimalStart(), vrefs, [1,5,5,1]) + MPB.optimize!(m) + + termination_status = MPB.getattribute(m, MPB.TerminationStatus()) + @test termination_status == MPB.Success + + primal_status = MPB.getattribute(m, MPB.PrimalStatus()) + @test primal_status == MPB.FeasiblePoint end end + # Same as above but no hessian callback -type HS071_2 <: MathProgBase.AbstractNLPEvaluator +type HS071_2 <: MPB.AbstractNLPEvaluator end # hs071 @@ -129,7 +143,7 @@ end # Start at (1,5,5,1) # End at (1.000..., 4.743..., 3.821..., 1.379...) -function MathProgBase.initialize(d::HS071_2, requested_features::Vector{Symbol}) +function MPB.initialize(d::HS071_2, requested_features::Vector{Symbol}) for feat in requested_features if !(feat in [:Grad, :Jac]) error("Unsupported feature $feat") @@ -139,50 +153,60 @@ function MathProgBase.initialize(d::HS071_2, requested_features::Vector{Symbol}) end end -MathProgBase.features_available(d::HS071_2) = [:Grad, :Jac] +MPB.features_available(d::HS071_2) = [:Grad, :Jac] -MathProgBase.eval_f(d::HS071_2, x) = MathProgBase.eval_f(HS071(), x) +MPB.eval_f(d::HS071_2, x) = MPB.eval_f(HS071(), x) -MathProgBase.eval_g(d::HS071_2, g, x) = MathProgBase.eval_g(HS071(), g, x) +MPB.eval_g(d::HS071_2, g, x) = MPB.eval_g(HS071(), g, x) -MathProgBase.eval_grad_f(d::HS071_2, grad_f, x) = MathProgBase.eval_grad_f(HS071(), grad_f, x) +MPB.eval_grad_f(d::HS071_2, grad_f, x) = MPB.eval_grad_f(HS071(), grad_f, x) -MathProgBase.jac_structure(d::HS071_2) = MathProgBase.jac_structure(HS071()) +MPB.jac_structure(d::HS071_2) = MPB.jac_structure(HS071()) -MathProgBase.eval_jac_g(d::HS071_2, J, x) = MathProgBase.eval_jac_g(HS071(), J, x) +MPB.eval_jac_g(d::HS071_2, J, x) = MPB.eval_jac_g(HS071(), J, x) function nlptest_nohessian(solver) @testset "Testing NLP without Hessian with $solver" begin - m = MathProgBase.NonlinearModel(solver) + m = MPB.NLPModel(solver) l = [1,1,1,1] u = [5,5,5,5] lb = [25, 40] ub = [Inf, 40] - MathProgBase.loadproblem!(m, 4, 2, l, u, lb, ub, :Min, HS071_2()) - MathProgBase.setwarmstart!(m,[1,5,5,1]) + vrefs = MPB.loadnlp!(m, 4, 2, l, u, lb, ub, MPB.MinSense, HS071_2()) + MPB.setattribute!(m, MPB.VariablePrimalStart(), vrefs, [1,5,5,1]) + + MPB.optimize!(m) + + termination_status = MPB.getattribute(m, MPB.TerminationStatus()) + @test termination_status == MPB.Success + + primal_status = MPB.getattribute(m, MPB.PrimalStatus()) + @test primal_status == MPB.FeasiblePoint - MathProgBase.optimize!(m) - stat = MathProgBase.status(m) + primal_sol = MPB.getattribute(m, MPB.VariablePrimal(), v) + @test isapprox(primal_sol[1], 1.0000000000000000, atol=1e-5) + @test isapprox(primal_sol[2], 4.7429996418092970, atol=1e-5) + @test isapprox(primal_sol[3], 3.8211499817883077, atol=1e-5) + @test isapprox(primal_sol[4], 1.3794082897556983, atol=1e-5) - @test stat == :Optimal - x = MathProgBase.getsolution(m) - @test isapprox(x[1], 1.0000000000000000, atol=1e-5) - @test isapprox(x[2], 4.7429996418092970, atol=1e-5) - @test isapprox(x[3], 3.8211499817883077, atol=1e-5) - @test isapprox(x[4], 1.3794082897556983, atol=1e-5) - @test isapprox(MathProgBase.getobjval(m), 17.014017145179164, atol=1e-5) + obj_val = MPB.getattribute(m, MPB.ObjectiveValue()) + @test isapprox(obj_val, 17.014017145179164, atol=1e-5) # Test that a second call to optimize! works - MathProgBase.setwarmstart!(m,[1,5,5,1]) - MathProgBase.optimize!(m) - stat = MathProgBase.status(m) - @test stat == :Optimal + MPB.setattribute!(m, MPB.VariablePrimalStart(), vrefs, [1,5,5,1]) + MPB.optimize!(m) + + termination_status = MPB.getattribute(m, MPB.TerminationStatus()) + @test termination_status == MPB.Success + + primal_status = MPB.getattribute(m, MPB.PrimalStatus()) + @test primal_status == MPB.FeasiblePoint end end -# a test for convex nonlinear solvers -type QCQP <: MathProgBase.AbstractNLPEvaluator +# a test for convex nonlinear solvers +type QCQP <: MPB.AbstractNLPEvaluator end # min x - y @@ -191,7 +215,7 @@ end # solution: x+y = -1/3 # optimal objective -1-4/sqrt(3) -function MathProgBase.initialize(d::QCQP, requested_features::Vector{Symbol}) +function MPB.initialize(d::QCQP, requested_features::Vector{Symbol}) for feat in requested_features if !(feat in [:Grad, :Jac, :Hess]) error("Unsupported feature $feat") @@ -201,30 +225,30 @@ function MathProgBase.initialize(d::QCQP, requested_features::Vector{Symbol}) end end -MathProgBase.features_available(d::QCQP) = [:Grad, :Jac, :Hess] +MPB.features_available(d::QCQP) = [:Grad, :Jac, :Hess] -MathProgBase.eval_f(d::QCQP, x) = x[1]-x[2] +MPB.eval_f(d::QCQP, x) = x[1]-x[2] -function MathProgBase.eval_g(d::QCQP, g, x) +function MPB.eval_g(d::QCQP, g, x) g[1] = x[1] + x[1]^2 + x[1]*x[2] + x[2]^2 end -function MathProgBase.eval_grad_f(d::QCQP, grad_f, x) +function MPB.eval_grad_f(d::QCQP, grad_f, x) grad_f[1] = 1 grad_f[2] = -1 end -MathProgBase.jac_structure(d::QCQP) = [1,1],[1,2] +MPB.jac_structure(d::QCQP) = [1,1],[1,2] # lower triangle only -MathProgBase.hesslag_structure(d::QCQP) = [1,2,2],[1,1,2] +MPB.hesslag_structure(d::QCQP) = [1,2,2],[1,1,2] -function MathProgBase.eval_jac_g(d::QCQP, J, x) +function MPB.eval_jac_g(d::QCQP, J, x) J[1] = 1 + 2x[1] + x[2] J[2] = x[1]+2x[2] end -function MathProgBase.eval_hesslag(d::QCQP, H, x, σ, μ) +function MPB.eval_hesslag(d::QCQP, H, x, σ, μ) # Again, only lower left triangle # Objective, linear @@ -237,39 +261,52 @@ end function convexnlptest(solver) @testset "Testing convex NLP with $solver" begin - m = MathProgBase.NonlinearModel(solver) + m = MPB.NonlinearModel(solver) l = [-2,-2] u = [2,2] lb = [-Inf] ub = [1.0] - MathProgBase.loadproblem!(m, 2, 1, l, u, lb, ub, :Min, QCQP()) + vrefs = MPB.loadnlp!(m, 2, 1, l, u, lb, ub, MPB.MinSense, QCQP()) - MathProgBase.optimize!(m) - stat = MathProgBase.status(m) + MPB.optimize!(m) + + termination_status = MPB.getattribute(m, MPB.TerminationStatus()) + @test termination_status == MPB.Success + + primal_status = MPB.getattribute(m, MPB.PrimalStatus()) + @test primal_status == MPB.FeasiblePoint + + primal_sol = MPB.getattribute(m, MPB.VariablePrimal(), v) + @test isapprox(primal_sol[1]+primal_sol[2], -1/3, atol=1e-3) + + obj_val = MPB.getattribute(m, MPB.ObjectiveValue()) + @test isapprox(obj_val, -1-4/sqrt(3), atol=1e-5) - @test stat == :Optimal - x = MathProgBase.getsolution(m) - @test isapprox(x[1]+x[2], -1/3, atol=1e-3) - @test isapprox(MathProgBase.getobjval(m), -1-4/sqrt(3), atol=1e-5) # Test that a second call to optimize! works - MathProgBase.optimize!(m) - stat = MathProgBase.status(m) - @test stat == :Optimal + # the line below was added during break_everything and may break this test + MPB.setattribute!(m, MPB.VariablePrimalStart(), vrefs, [0.0,0.0]) + + MPB.optimize!(m) + + termination_status = MPB.getattribute(m, MPB.TerminationStatus()) + @test termination_status == MPB.Success + + primal_status = MPB.getattribute(m, MPB.PrimalStatus()) + @test primal_status == MPB.FeasiblePoint end end # a test for unconstrained nonlinear solvers - -type Rosenbrock <: MathProgBase.AbstractNLPEvaluator +type Rosenbrock <: MPB.AbstractNLPEvaluator end # min (1-x)^2 + 100*(y-x^2)^2 # solution: (x,y) = (1,1) # optimal objective 0 -function MathProgBase.initialize(d::Rosenbrock, requested_features::Vector{Symbol}) +function MPB.initialize(d::Rosenbrock, requested_features::Vector{Symbol}) for feat in requested_features if !(feat in [:Grad, :Hess]) error("Unsupported feature $feat") @@ -279,20 +316,20 @@ function MathProgBase.initialize(d::Rosenbrock, requested_features::Vector{Symbo end end -MathProgBase.features_available(d::Rosenbrock) = [:Grad, :Hess] +MPB.features_available(d::Rosenbrock) = [:Grad, :Hess] -MathProgBase.eval_f(d::Rosenbrock, x) = (1-x[1])^2 + 100*(x[2]-x[1]^2)^2 +MPB.eval_f(d::Rosenbrock, x) = (1-x[1])^2 + 100*(x[2]-x[1]^2)^2 -MathProgBase.eval_g(d::Rosenbrock, g, x) = nothing +MPB.eval_g(d::Rosenbrock, g, x) = nothing -function MathProgBase.eval_grad_f(d::Rosenbrock, grad_f, x) +function MPB.eval_grad_f(d::Rosenbrock, grad_f, x) grad_f[1] = -2*(1-x[1]) - 400*x[1]*(x[2]-x[1]^2) grad_f[2] = 200*(x[2]-x[1]^2) end -MathProgBase.hesslag_structure(d::Rosenbrock) = [1,2,2],[1,1,2] +MPB.hesslag_structure(d::Rosenbrock) = [1,2,2],[1,1,2] -function MathProgBase.eval_hesslag(d::Rosenbrock, H, x, σ, μ) +function MPB.eval_hesslag(d::Rosenbrock, H, x, σ, μ) # Again, only lower left triangle H[1] = σ*(2+100*(8x[1]^2-4*(x[2]-x[1]^2))) # d/dx^2 @@ -303,26 +340,41 @@ end function rosenbrocktest(solver) @testset "Testing NLP on the Rosenbrock function with $solver" begin - m = MathProgBase.NonlinearModel(solver) + m = MPB.NLPModel(solver) l = [-Inf,-Inf] u = [Inf,Inf] lb = Float64[] ub = Float64[] - MathProgBase.loadproblem!(m, 2, 0, l, u, lb, ub, :Min, Rosenbrock()) + MPB.loadnlp!(m, 2, 0, l, u, lb, ub, MPB.MinSense, Rosenbrock()) + MPB.setattribute!(m, MPB.VariablePrimalStart(), vrefs, [10.0,10.0]) - MathProgBase.setwarmstart!(m,[10.0,10.0]) - MathProgBase.optimize!(m) - stat = MathProgBase.status(m) + MPB.optimize!(m) + stat = MPB.status(m) - @test stat == :Optimal - x = MathProgBase.getsolution(m) - @test isapprox(x[1], 1.0, atol=1e-5) - @test isapprox(x[2], 1.0, atol=1e-5) - @test isapprox(MathProgBase.getobjval(m), 0.0, atol=1e-5) + termination_status = MPB.getattribute(m, MPB.TerminationStatus()) + @test termination_status == MPB.Success + + primal_status = MPB.getattribute(m, MPB.PrimalStatus()) + @test primal_status == MPB.FeasiblePoint + + + primal_sol = MPB.getattribute(m, MPB.VariablePrimal(), v) + @test isapprox(primal_sol[1], 1.0, atol=1e-5) + @test isapprox(primal_sol[2], 1.0, atol=1e-5) + + obj_val = MPB.getattribute(m, MPB.ObjectiveValue()) + @test isapprox(obj_val, 0.0, atol=1e-5) # Test that a second call to optimize! works - MathProgBase.optimize!(m) - stat = MathProgBase.status(m) - @test stat == :Optimal + # the line below was added during break_everything and may break this test + MPB.setattribute!(m, MPB.VariablePrimalStart(), vrefs, [10.0,10.0]) + + MPB.optimize!(m) + + termination_status = MPB.getattribute(m, MPB.TerminationStatus()) + @test termination_status == MPB.Success + + primal_status = MPB.getattribute(m, MPB.PrimalStatus()) + @test primal_status == MPB.FeasiblePoint end end diff --git a/test/runtests.jl b/test/runtests.jl index 32a6666..228523c 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -1,5 +1,7 @@ using GLPKMathProgInterface, Ipopt, ECOS +const MPB = MathProgBase + lp_solver = GLPKSolverLP() ip_solver = GLPKSolverMIP() conic_solver = ECOSSolver(verbose=false) From b509ca67f08e1afc92b5c904a730d69f5e823f12 Mon Sep 17 00:00:00 2001 From: Miles Lubin Date: Fri, 16 Jun 2017 17:15:48 -0400 Subject: [PATCH 66/83] restructure docs --- docs/make.jl | 13 ++------ docs/src/attributes.md | 66 ----------------------------------------- docs/src/basics.md | 20 ------------- docs/src/constraints.md | 15 ---------- docs/src/duals.md | 7 ----- docs/src/highlevel.md | 2 ++ docs/src/index.md | 5 ++++ docs/src/nlp.md | 35 ---------------------- docs/src/objectives.md | 10 ------- docs/src/sets.md | 17 ----------- docs/src/statuscodes.md | 26 ---------------- docs/src/variables.md | 14 --------- 12 files changed, 9 insertions(+), 221 deletions(-) delete mode 100644 docs/src/attributes.md delete mode 100644 docs/src/basics.md delete mode 100644 docs/src/constraints.md delete mode 100644 docs/src/duals.md delete mode 100644 docs/src/nlp.md delete mode 100644 docs/src/objectives.md delete mode 100644 docs/src/sets.md delete mode 100644 docs/src/statuscodes.md delete mode 100644 docs/src/variables.md diff --git a/docs/make.jl b/docs/make.jl index d000b9a..b35eaa7 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -5,18 +5,9 @@ makedocs( sitename = "MathProgBase", pages = [ "Introduction" => "index.md", + "Solver Interface API" => "apireference.md", "High-level Interfaces" => "highlevel.md", - "Solver Interface" => [ - "Basics" => "basics.md", - "Variables" => "variables.md", - "Objectives" => "objectives.md", - "Constraints" => "constraints.md", - "Sets" => "sets.md", - "Attributes" => "attributes.md", - "Status Codes" => "statuscodes.md", - "Duals" => "duals.md", - "NLP" => "nlp.md"], - "Choosing Solver" => "choosingsolver.md" + "Choosing Solvers" => "choosingsolver.md" ] ) diff --git a/docs/src/attributes.md b/docs/src/attributes.md deleted file mode 100644 index c9c50cf..0000000 --- a/docs/src/attributes.md +++ /dev/null @@ -1,66 +0,0 @@ -```@meta -CurrentModule = MathProgBase -``` - -These are used to get and set properties of the model. - -```@docs -AbstractAttribute -cangetattribute -getattribute -cansetattribute -setattribute! -``` - -## Scalar Attributes - -```@docs -ObjectiveValue -ObjectiveBound -RelativeGap -SolveTime -Sense -SimplexIterations -BarrierIterations -NodeCount -RawSolver -ResultCount -VariableCount -ConstraintCount -SupportsVariablewiseConstraint -SupportsAffineConstraint -SupportsQuadraticConstraint -TerminationStatus -PrimalStatus -DualStatus -``` - -## Variable Attributes - -These attributes are associated with variables. Calls to `getattribute` and `setattribute!` should include as an argument a single `VariableReference` or a vector of `VariableReference` objects. - -```@docs -VariablePrimalStart -VariableLowerBoundDualStart -VariableUpperBoundDualStart -VariableLowerBound -VariableUpperBound -VariablePrimal -VariableLowerBoundDual -VariableUpperBoundDual -VariableBasisStatus -``` - -## Constraint Attributes - -These attributes are associated with constraints. Calls to `getattribute` and `setattribute!` should include as an argument a single `ConstraintReference` or a vector of `ConstriaintReference{T}` objects. - -```@docs -ConstraintPrimalStart -ConstraintDualStart -ConstraintPrimal -ConstraintDual -ConstraintBasisStatus -``` - - diff --git a/docs/src/basics.md b/docs/src/basics.md deleted file mode 100644 index f2e8f22..0000000 --- a/docs/src/basics.md +++ /dev/null @@ -1,20 +0,0 @@ - -```@meta -CurrentModule = MathProgBase -``` - -Some introduction to MPB API. List basic standalone methods. - -```@docs -AbstractModel -AbstractNLPModel -AbstractMathProgSolver -``` - - -```@docs -Model -NLPModel -optimize! -freemodel! -``` diff --git a/docs/src/constraints.md b/docs/src/constraints.md deleted file mode 100644 index 47b47d1..0000000 --- a/docs/src/constraints.md +++ /dev/null @@ -1,15 +0,0 @@ -```@meta -CurrentModule = MathProgBase -``` - -How to add and modify constraints. -```@docs -VariablewiseConstraintReference -AffineConstraintReference -QuadraticConstraintReference -candelete(::AbstractMathProgModel,::ConstraintReference) -isvalid(::AbstractMathProgModel,::ConstraintReference) -delete!(::AbstractMathProgModel,::ConstraintReference) -addconstraint! -modifyconstraint! -``` diff --git a/docs/src/duals.md b/docs/src/duals.md deleted file mode 100644 index b25b1b3..0000000 --- a/docs/src/duals.md +++ /dev/null @@ -1,7 +0,0 @@ -```@meta -CurrentModule = MathProgBase -``` - - -We take the convention that duals on variable lower bounds should be nonnegative, duals on variable upper bounds should be nonpositive, and duals on closed convex cones should belong to the dual cone. - diff --git a/docs/src/highlevel.md b/docs/src/highlevel.md index c69c4a0..af971af 100644 --- a/docs/src/highlevel.md +++ b/docs/src/highlevel.md @@ -2,6 +2,8 @@ CurrentModule = MathProgBase ``` +# High-level Interfaces + **These docs are out of date. We need to update the high-level interfaces for new statuses.** ## Linear Programming diff --git a/docs/src/index.md b/docs/src/index.md index cabee06..02b5ad8 100644 --- a/docs/src/index.md +++ b/docs/src/index.md @@ -1,3 +1,8 @@ # MathProgBase [MathProgBase.jl](https://github.com/JuliaOpt/MathProgBase.jl) is a standardized API for Mathematical Optimization solvers. [JuMP](https://github.com/JuliaOpt/JuMP.jl) uses MathProgBase as a solver-independent low-level backend, but MathProgBase may be used freely without JuMP. In addition to the low-level API, MathProgBase provides one-shot functions for linear, mixed-integer, and quadratic optimization problems. + +```@contents +Pages = ["apireference.md","highlevel.md","choosingsolver.md"] +Depth = 3 +``` diff --git a/docs/src/nlp.md b/docs/src/nlp.md deleted file mode 100644 index ee3ddb1..0000000 --- a/docs/src/nlp.md +++ /dev/null @@ -1,35 +0,0 @@ -```@meta - CurrentModule = MathProgBase -``` - -# NonLinear Programming Interface (NLP) - - -## NLP Methods - -```@docs -loadnlp! -initialize -features_available -eval_f -eval_grad_f -jac_structure -hesslag_structure -eval_jac_g -eval_jac_prod -eval_jac_prod_t -eval_hesslag_prod -eval_hesslag -isobjlinear(::AbstractNLPEvaluator) -isobjquadratic(::AbstractNLPEvaluator) -isconstrlinear(::AbstractNLPEvaluator, i::Integer) -obj_expr -constr_expr -``` - -## NLP Attributes - -```@docs -ConstraintNLPDual -ConstraintNLPDualStart -``` diff --git a/docs/src/objectives.md b/docs/src/objectives.md deleted file mode 100644 index 09b8896..0000000 --- a/docs/src/objectives.md +++ /dev/null @@ -1,10 +0,0 @@ -```@meta -CurrentModule = MathProgBase -``` - -How to add and set objectives. -```@docs -setobjective! -modifyobjective! -getobjective -``` diff --git a/docs/src/sets.md b/docs/src/sets.md deleted file mode 100644 index 00fd536..0000000 --- a/docs/src/sets.md +++ /dev/null @@ -1,17 +0,0 @@ -```@meta -CurrentModule = MathProgBase -``` - - -List of sets. -```@docs -NonNegative -NonPositive -Zero -Interval -SecondOrderCone -Integers -Binaries -SOS1 -SOS2 -``` diff --git a/docs/src/statuscodes.md b/docs/src/statuscodes.md deleted file mode 100644 index 5c9efa3..0000000 --- a/docs/src/statuscodes.md +++ /dev/null @@ -1,26 +0,0 @@ -```@meta -CurrentModule = MathProgBase -``` - - -## Termination Status - -The `TerminationStatus` attribute is meant to explain the reason why the solver stopped executing. The value of the attribute is of type `TerminationStatusCode`. - -```@docs -TerminationStatusCode -``` - -## Result Status - -The `PrimalStatus` and `DualStatus` attributes are meant to explain how to interpret the result returned by the solver. The value of the attributes are of type `ResultStatusCode`. - -```@docs -ResultStatusCode -``` - -## Basis Status - -```@docs -BasisStatusCode -``` diff --git a/docs/src/variables.md b/docs/src/variables.md deleted file mode 100644 index 61fa9c8..0000000 --- a/docs/src/variables.md +++ /dev/null @@ -1,14 +0,0 @@ - -```@meta -CurrentModule = MathProgBase -``` - -```@docs -VariableReference -candelete(::AbstractMathProgModel,::VariableReference) -isvalid(::AbstractMathProgModel,::VariableReference) -delete!(::AbstractMathProgModel,::VariableReference) -addvariables! -addvariable! -``` - From 57c1480e20befc813b4ec6616876395f3aab5acb Mon Sep 17 00:00:00 2001 From: Miles Lubin Date: Fri, 16 Jun 2017 17:21:12 -0400 Subject: [PATCH 67/83] missing file --- docs/src/apireference.md | 194 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 194 insertions(+) create mode 100644 docs/src/apireference.md diff --git a/docs/src/apireference.md b/docs/src/apireference.md new file mode 100644 index 0000000..27dbfd3 --- /dev/null +++ b/docs/src/apireference.md @@ -0,0 +1,194 @@ +```@meta +CurrentModule = MathProgBase +``` + +# Solver Interface API + +Some introduction to MPB API. List basic standalone methods. + +```@docs +AbstractModel +AbstractNLPModel +AbstractMathProgSolver +``` + + +```@docs +Model +NLPModel +optimize! +freemodel! +``` + +## Variables + + +```@docs +VariableReference +candelete(::AbstractMathProgModel,::VariableReference) +isvalid(::AbstractMathProgModel,::VariableReference) +delete!(::AbstractMathProgModel,::VariableReference) +addvariables! +addvariable! +``` + +## Objectives + +How to add and set objectives. +```@docs +setobjective! +modifyobjective! +getobjective +``` + +## Constraints + +How to add and modify constraints. +```@docs +VariablewiseConstraintReference +AffineConstraintReference +QuadraticConstraintReference +candelete(::AbstractMathProgModel,::ConstraintReference) +isvalid(::AbstractMathProgModel,::ConstraintReference) +delete!(::AbstractMathProgModel,::ConstraintReference) +addconstraint! +modifyconstraint! +``` + +## Sets + +List of sets. +```@docs +NonNegative +NonPositive +Zero +Interval +SecondOrderCone +Integers +Binaries +SOS1 +SOS2 +``` + +## Attributes + +These are used to get and set properties of the model. + +```@docs +AbstractAttribute +cangetattribute +getattribute +cansetattribute +setattribute! +``` + +### Scalar Attributes + +```@docs +ObjectiveValue +ObjectiveBound +RelativeGap +SolveTime +Sense +SimplexIterations +BarrierIterations +NodeCount +RawSolver +ResultCount +VariableCount +ConstraintCount +SupportsVariablewiseConstraint +SupportsAffineConstraint +SupportsQuadraticConstraint +TerminationStatus +PrimalStatus +DualStatus +``` + +### Variable Attributes + +These attributes are associated with variables. Calls to `getattribute` and `setattribute!` should include as an argument a single `VariableReference` or a vector of `VariableReference` objects. + +```@docs +VariablePrimalStart +VariableLowerBoundDualStart +VariableUpperBoundDualStart +VariableLowerBound +VariableUpperBound +VariablePrimal +VariableLowerBoundDual +VariableUpperBoundDual +VariableBasisStatus +``` + +### Constraint Attributes + +These attributes are associated with constraints. Calls to `getattribute` and `setattribute!` should include as an argument a single `ConstraintReference` or a vector of `ConstriaintReference{T}` objects. + +```@docs +ConstraintPrimalStart +ConstraintDualStart +ConstraintPrimal +ConstraintDual +ConstraintBasisStatus +``` + +## Status Codes + +### Termination Status + +The `TerminationStatus` attribute is meant to explain the reason why the solver stopped executing. The value of the attribute is of type `TerminationStatusCode`. + +```@docs +TerminationStatusCode +``` + +### Result Status + +The `PrimalStatus` and `DualStatus` attributes are meant to explain how to interpret the result returned by the solver. The value of the attributes are of type `ResultStatusCode`. + +```@docs +ResultStatusCode +``` + +### Basis Status + +```@docs +BasisStatusCode +``` + +## Duals + +We take the convention that duals on variable lower bounds should be nonnegative, duals on variable upper bounds should be nonpositive, and duals on closed convex cones should belong to the dual cone. + +## Nonlinear Programming (NLP) + + +### NLP Methods + +```@docs +loadnlp! +initialize +features_available +eval_f +eval_grad_f +jac_structure +hesslag_structure +eval_jac_g +eval_jac_prod +eval_jac_prod_t +eval_hesslag_prod +eval_hesslag +isobjlinear(::AbstractNLPEvaluator) +isobjquadratic(::AbstractNLPEvaluator) +isconstrlinear(::AbstractNLPEvaluator, i::Integer) +obj_expr +constr_expr +``` + +### NLP Attributes + +```@docs +ConstraintNLPDual +ConstraintNLPDualStart +``` From 2f685d0de957d8a3d21007ba2f50ef040562fa22 Mon Sep 17 00:00:00 2001 From: Miles Lubin Date: Fri, 16 Jun 2017 18:34:26 -0400 Subject: [PATCH 68/83] getters for constraint and objective data --- docs/src/apireference.md | 7 +++++- src/SolverInterface/constraints.jl | 33 ++++++++++++++++++++++++++ src/SolverInterface/objectives.jl | 37 ++++++++++++++++++++++++------ 3 files changed, 69 insertions(+), 8 deletions(-) diff --git a/docs/src/apireference.md b/docs/src/apireference.md index 27dbfd3..38bcce6 100644 --- a/docs/src/apireference.md +++ b/docs/src/apireference.md @@ -38,7 +38,8 @@ How to add and set objectives. ```@docs setobjective! modifyobjective! -getobjective +getobjectiveconstant +getobjectiveaffine ``` ## Constraints @@ -53,6 +54,9 @@ isvalid(::AbstractMathProgModel,::ConstraintReference) delete!(::AbstractMathProgModel,::ConstraintReference) addconstraint! modifyconstraint! +getconstraintconstant +getconstraintaffine +getconstraintquadratic ``` ## Sets @@ -78,6 +82,7 @@ These are used to get and set properties of the model. AbstractAttribute cangetattribute getattribute +getattribute! cansetattribute setattribute! ``` diff --git a/src/SolverInterface/constraints.jl b/src/SolverInterface/constraints.jl index 0d5b0ef..7542450 100644 --- a/src/SolverInterface/constraints.jl +++ b/src/SolverInterface/constraints.jl @@ -135,3 +135,36 @@ modifyconstraint!(m, c, NonPositive) # errors ``` """ function modifyconstraint! end + +""" + getconstraintconstant(m::AbstractMathProgModel, c::ConstraintReference, i::Int) + +Return the constant term of the `i`th row of the constraint corresponding to `c`. +""" +function getconstraintconstant end + +""" + getconstraintaffine(m::AbstractMathProgModel, c::ConstraintReference) + +Return the ``A`` matrix of the constraint corresponding to `c` in triplet form `(row,varref,coef)` where `row` is an integer, `varref` is a `VariableReference`, and `coef` is a coefficient. Output is a tuple of three vectors. + + getconstraintaffine(m::AbstractMathProgModel, c::ConstraintReference, i::Int) + +Return the `i`th row of the ``A`` matrix of the constraint corresponding to `c` in tuple form `(varref,coef)` where `varref` is a `VariableReference`, and `coef` is a coefficient. Output is a tuple of two vectors. + + getconstraintaffine(m::AbstractMathProgModel, c::ConstraintReference, i::Int, v::VariableReference) + +Return the element of the ``A`` matrix of the constraint corresponding to `c` in row `i` and variable `v`. +""" +function getconstraintaffine end + +""" + getconstraintquadratic(m::AbstractMathProgModel, c::ConstraintReference, i::Int) + +Return the ``Q`` matrix of the `i`th row of the constraint corresponding to `c` in triplet form `(varref_a,varref_b,coef)` where `varref_a` is a `VariableReference`, `varref_b` is a `VariableReference`, and `coef` is a coefficient. Output is a tuple of three vectors. The ``Q`` matrix must be symmetric, and only one of the two symmetric elements is returned. + + getconstraintquadratic(m::AbstractMathProgModel, c::ConstraintReference, i::Int, v1::VariableReference, v2::VariableReference) + +Return the element `(v1,v2)` of the ``Q`` matrix of the `i`th row of the constraint corresponding to `c`. +""" +function getconstraintquadratic end diff --git a/src/SolverInterface/objectives.jl b/src/SolverInterface/objectives.jl index 6102160..f308ac7 100644 --- a/src/SolverInterface/objectives.jl +++ b/src/SolverInterface/objectives.jl @@ -1,11 +1,11 @@ """ - setobjective!(m::AbstractMathProgModel, N::Int, b, a_varidx, a_coef, Q_vari, Q_varj, Q_coef) + setobjective!(m::AbstractMathProgModel, b, a_varref::Vector{VariableReference}, a_coef, Q_vari::Vector{VariableReference}, Q_varj::Vector{VariableReference}, Q_coef, N::Int=1) Set the `N`'th objective in the model `m` to be ```math a^Tx + b + \\frac{1}{2}x^TQx ``` -where ``a`` is a sparse vector specified in tuple form by `a_varidx`, and +where ``a`` is a sparse vector specified in tuple form by `a_varref`, and `a_coef`; ``b`` is a scalar; and the symmetric matrix ``Q`` is defined by the triplets in `Q_vari`, `Q_varj`, `Q_coef`. @@ -13,8 +13,20 @@ Duplicate indices in either the ``a`` vector or the ``Q`` matrix are accepted an summed together. Off-diagonal entries of ``Q`` will be mirrored, so either the upper triangular or lower triangular entries of ``Q`` should be provided. If entries for both ``(i,j)`` and ``(j,i)`` are provided, these are considered -duplicate terms. `a_varidx`, `Q_vari`, `Q_varj` should be collections of +duplicate terms. `a_varref`, `Q_vari`, `Q_varj` should be collections of `VariableReference` objects. + + setobjective!(m::AbstractMathProgModel, b, a_varref::Vector{VariableReference}, a_coef, N::Int=1) + +Set the `N`'th objective in the model `m` to be +```math +a^Tx + b +``` +where ``a`` is a sparse vector specified in tuple form by `a_varref` and +`a_coef` and ``b`` is a scalar. + +Duplicate indices in either the ``a`` vector are accepted and will be +summed together. """ function setobjective! end @@ -78,10 +90,21 @@ modifyobjective!(m, 1, [v1, v2], [v1, v1], [1.0, 2.0]) function modifyobjective! end """ - getobjective(m, i:Int) + getobjectiveconstant(m, i::Int=1) -Returns the `i`'th objective as the tuple `(b, a_varidx, a_coef, Q_vari, Q_varj, Q_coef)`. +Return the constant term in the `i`'th objective. +""" +function getobjectiveconstant end + +""" + getobjectiveaffine(m, i::Int=1) -The elements in the tuple are the same as those defined in `addobjective!`. +Return the affine part of the `i`'th objective in tuple form `(varref,coef)` where `varref` is a `VariableReference`, and `coef` is a coefficient. Output is a tuple of two vectors. + + getobjectiveaffine(m, v::VariableReference, i::Int=1) + +Return the coefficient for the variable `v` in the affine part of the `i`'th objective. """ -function getobjective end +function getobjectiveaffine end + +## TODO: getobjectivequadratic From f795d13c85205443e1aa2d10bb37673a6227bc94 Mon Sep 17 00:00:00 2001 From: Carleton Coffrin Date: Fri, 16 Jun 2017 19:06:21 -0400 Subject: [PATCH 69/83] WIP: Migrated First Conic Model (#191) * preliminary migration of nlp tests * WIP: adding first conic example --- test/conicinterface.jl | 57 +++++++++++++++++++++++++++++++----------- 1 file changed, 42 insertions(+), 15 deletions(-) diff --git a/test/conicinterface.jl b/test/conicinterface.jl index 6dad8b7..50fa492 100644 --- a/test/conicinterface.jl +++ b/test/conicinterface.jl @@ -9,7 +9,7 @@ using Base.Test using MathProgBase """ -function coniclineartest(solver::MathProgBase.AbstractMathProgSolver;duals=false, tol=1e-6) +function coniclineartest(solver::MathProgBase.AbstractMathProgSolver; duals=false, tol=1e-6) @testset "Testing linear problems through conic interface with $solver" begin # Problem LIN1 - all vars in nonneg cone # min -3x - 2y - 4z @@ -23,21 +23,48 @@ function coniclineartest(solver::MathProgBase.AbstractMathProgSolver;duals=false A = [ 1.0 1.0 1.0; 0.0 1.0 1.0] b = [ 3.0, 2.0] - m = MathProgBase.ConicModel(solver) - MathProgBase.loadproblem!(m, c, A, b, [(:Zero,1:2)], [(:NonNeg, 1:3)]) + m = MPB.Model(solver) + + #MathProgBase.loadproblem!(m, c, A, b, [(:Zero,1:2)], [(:NonNeg, 1:3)]) + v = MPB.addvariables!(m, 3) + + MPB.setattribute!(m, MPB.Sense(), MPB.MinSense) + + vc = MPB.addconstraint!(m, v, MPB.NonNegative(3)) + c = MPB.addconstraint!(m, b, -A, MPB.Zero(2)) + + MPB.setobjective!(m, 1, 0.0, v, c) + MathProgBase.optimize!(m) - @test MathProgBase.status(m) == :Optimal - @test isapprox(MathProgBase.getobjval(m), -11, atol=tol) - @test isapprox(MathProgBase.getsolution(m)[1], 1.0, atol=tol) - @test isapprox(MathProgBase.getsolution(m)[2], 0.0, atol=tol) - @test isapprox(MathProgBase.getsolution(m)[3], 2.0, atol=tol) + + termination_status = MPB.getattribute(m, MPB.TerminationStatus()) + @test termination_status == MPB.Success + + primal_status = MPB.getattribute(m, MPB.PrimalStatus()) + @test primal_status == MPB.FeasiblePoint + + obj = MPB.getattribute(m, MPB.ObjectiveValue()) + @test isapprox(obj, -11, atol=tol) + + p_sol = MPB.getattribute(m, MPB.VariablePrimal(), v) + @test isapprox(p_sol[1], 1.0, atol=tol) + @test isapprox(p_sol[2], 0.0, atol=tol) + @test isapprox(p_sol[3], 2.0, atol=tol) if duals - d = MathProgBase.getdual(m) - @test isapprox(d[1], 3.0, atol=tol) - @test isapprox(d[2], 1.0, atol=tol) - vardual = c + A'd - var = MathProgBase.getvardual(m) - @test isapprox(vardual, var, atol=tol) + @test MPB.cangetattribute(m, MPB.DualStatus()) + @test MPB.cangetattribute(m, MPB.ConstraintDual(), c) + @test MPB.cangetattribute(m, MPB.ConstraintDual(), vc) + + dual_status = MPB.getattribute(m, MPB.DualStatus()) + @test dual_status == MPB.FeasiblePoint + + d_sol = MPB.getattribute(m, MPB.ConstraintDual(), c) + @test isapprox(d_sol[1], 3.0, atol=tol) + @test isapprox(d_sol[2], 1.0, atol=tol) + + vardual = c + A'd_sol + vd_sol = MPB.getattribute(m, MPB.ConstraintDual(), vc) + @test isapprox(vardual, vd_sol, atol=tol) end end @@ -59,7 +86,7 @@ function coniclineartest(solver::MathProgBase.AbstractMathProgSolver;duals=false 0.0 1.0 0.0; 0.0 0.0 -1.0] b = [ 3.0, 2.0, 0.0, 0.0, 0.0] - m = MathProgBase.ConicModel(solver) + m = MPB.ConicModel(solver) MathProgBase.loadproblem!(m,c, A, b, [(:Zero,1:2),(:NonPos,3:4),(:NonNeg,5)], [(:Free, 1:3)]) MathProgBase.optimize!(m) From dfa8cd841952be72550f2804df25773e5b4da6f7 Mon Sep 17 00:00:00 2001 From: Oscar Dowson Date: Fri, 16 Jun 2017 19:25:50 -0400 Subject: [PATCH 70/83] WIP: redo tests (#182) * tests * more test * MOre testing * more tests * More tests --- test/linproginterface.jl | 125 ++++++++++++++++++++++++++------------- 1 file changed, 83 insertions(+), 42 deletions(-) diff --git a/test/linproginterface.jl b/test/linproginterface.jl index c7c868f..e31ab51 100644 --- a/test/linproginterface.jl +++ b/test/linproginterface.jl @@ -2,68 +2,109 @@ using Base.Test using MathProgBase using MathProgBase.SolverInterface +const MPB = MathProgBase + +function test_result(m, v, c, termstatus, primalstatus, dualstatus, objval, varprim, vupdual, vlodual, conprim, condual) + @test MPB.cangetattribute(m, MPB.TerminationStatus()) + @test MPB.getattribute(m, MPB.TerminationStatus()) == termstatus + + @test MPB.cangetattribute(m, MPB.PrimalStatus()) + @test MPB.getattribute(m, MPB.PrimalStatus()) == primalstatus + + @test MPB.cangetattribute(m, MPB.DualStatus()) + # maybe solver doesn't return dual? + @test MPB.getattribute(m, MPB.DualStatus()) == dualstatus + + @test MPB.cangetattribute(m, MPB.ObjectiveValue()) + @test isapprox(MPB.getattribute(m, MPB.ObjectiveValue()), objval, atol=eps) + + @test MPB.cangetattribute(m, MPB.VariablePrimal(), v) + @test isapprox(MPB.getattribute(m, MPB.VariablePrimal(), v), varprim, atol=eps) + + @test MPB.cangetattribute(m, MPB.VariableUpperBoundDual(), v) + @test isapprox(MPB.getattribute(m, MPB.VariableUpperBoundDual(), v), vupdual, atol=eps) + + @test MPB.cangetattribute(m, MPB.VariableLowerBoundDual(), v) + @test isapprox(MPB.getattribute(m, MPB.VariableLowerBoundDual(), v), vlodual, atol=eps) + + @test MPB.cangetattribute(m, MPB.ConstraintPrimal(), c) + @test isapprox(MPB.getattribute(m, MPB.ConstraintPrimal(), c), conprim, atol=eps) + + @test MPB.cangetattribute(m, MPB.ConstraintDual(), c) + @test isapprox(MPB.getattribute(m, MPB.ConstraintDual(), c), condual, atol=eps) +end -""" function linprogsolvertest(solver::AbstractMathProgSolver, eps = Base.rtoldefault(Float64)) @testset "Testing LP interface with $solver" begin @testset "Basic interface" begin - m = LinearQuadraticModel(solver) + # Min -x Min -x + # s.t. x + y <= 1 or s.t. x + y - 1 ∈ NonPositive + # x, y >= 0 x, y >= 0 + m = MPB.Model(solver) - # Min -x - # s.t. x + y <= 1 - # x, y >= 0 - loadproblem!(m, [1. 1.], [0.,0.], [Inf, Inf], [-1.,0.], [-Inf],[1.], :Min) - @test numvar(m) == 2 - @test numconstr(m) == 1 - @test getvarLB(m) == [0.,0.] - @test getvarUB(m)[1] >= 1e20 - @test getvarUB(m)[2] >= 1e20 - @test getconstrLB(m)[1] < -1e30 - @test getconstrUB(m)[1] == 1.0 - @test getobj(m) == [-1.,0.] - @test getsense(m) == :Min + v = MPB.addvariables!(m, 2) - optimize!(m) - @test status(m) == :Optimal - @test isapprox(getobjval(m), -1, atol=eps) - @test isapprox(norm(getsolution(m) - [1.0, 0.0]), 0.0, atol=eps) - @test isapprox(getconstrsolution(m)[1], 1.0, atol=eps) - @test isapprox(getconstrduals(m)[1], -1.0, atol=eps) - @test isapprox(norm(getreducedcosts(m) - [0.0, 1.0]), 0.0, atol=eps) + @test MPB.cansetattribute(m, MPB.VariableLowerBound()) + MPB.setattribute!(m, MPB.VariableLowerBound(), v, [0, 0]) - setsense!(m, :Max) - # max x - setobj!(m, [1.0,0.0]) - optimize!(m) + @test MPB.cangetattribute(m, MPB.VariableLowerBound()) + @test isapprox(MPB.getattribute(m, MPB.VariableLowerBound(), v), [0.0, 0.0], atol=eps) - @test status(m) == :Optimal - @test isapprox(getobjval(m), 1, atol=eps) - @test isapprox(norm(getsolution(m) - [1.0, 0.0]), 0.0, atol=eps) - @test isapprox(getconstrsolution(m)[1], 1.0, atol=eps) - @test isapprox(getconstrduals(m)[1], 1.0, atol=eps) - @test isapprox(norm(getreducedcosts(m) - [0.0, -1.0]), 0.0, atol=eps) + @test MPB.cangetattribute(m, MPB.VariableUpperBound()) + @test all(MPB.getattribute(m, MPB.VariableUpperBound(), v) .>= 1e20) + + @test MPB.getattribute(m, SupportsAffineConstraint{MPB.NonPositive}()) + c = MPB.addconstraint!(m, -1, v, [1, 1], MPB.NonPositive(1)) + + @test MPB.getattribute(m, MPB.VariableCount()) == 2 + @test MPB.getattribute(m, MPB.ConstraintCount()) == 1 + + MPB.setattribute!(m, MPB.Sense(), MPB.MinSense) + + MPB.setobjective!(m, 1, 0.0, v, [-1.0, 0.0]) + + # TODO: query objective + # (b, a_varref, a_coef, qi, qj, qc) = MPB.getobjective(m) + # @test isapprox(b, 0.0, atol=eps) + # @test a_varref == v + # @test isapprox(a_coef, [-1.0, 0.0], atol=eps) + + MPB.optimize!(m) + + test_result(m, v, c, MPB.Success, MPB.FeasiblePoint, MPB.FeasiblePoint, -1, [1.0, 0.0], [0.0, 0.0], [0.0, 1.0], [1.0], [-1.0]) + + # change objective to Max +x + @test MPB.cansetattribute(m, MPB.Sense()) + MPB.setattribute!(m, MPB.Sense(), MPB.MaxSense) + MPB.modifyobjective!(m, 1, v[1], 1.0) + + MPB.optimize!(m) + + test_result(m, v, c, MPB.Success, MPB.FeasiblePoint, MPB.FeasiblePoint, 1, [1.0, 0.0], [0.0, -1.0], [0.0, 0.0], [1.0], [1.0]) # add new variable to get: # max x + 2z # s.t. x + y + z <= 1 # x,y,z >= 0 - addvar!(m, [1], [1.0], 0, Inf, 2.0) + z = MPB.addvariable!(m, c, [1]) + MPB.setattribute!(m, MPB.VariableLowerBound(), z, 0) + MPB.modifyobjective!(m, z, 2) - @test numvar(m) == 3 - @test numconstr(m) == 1 + @test MPB.getattribute(m, MPB.VariableCount()) == 3 + @test MPB.getattribute(m, MPB.ConstraintCount()) == 1 optimize!(m) - @test status(m) == :Optimal - @test isapprox(getobjval(m), 2, atol=eps) - @test isapprox(norm(getsolution(m) - [0.0, 0.0, 1.0]), 0.0, atol=eps) - @test isapprox(getconstrsolution(m)[1], 1.0, atol=eps) - @test isapprox(getconstrduals(m)[1], 2.0, atol=eps) - @test isapprox(norm(getreducedcosts(m) - [-1.0, -2.0, 0.0]), 0.0, atol=eps) + test_result(m, v, c, MPB.Success, MPB.FeasiblePoint, MPB.FeasiblePoint, 2, [0.0, 0.0, 1.0], [-1.0, -2.0, 0.0], [0.0, 0.0, 0.0], [1.0], [2.0]) + + MPB.setattribute!(m, MPB.VariableLowerBound(), v[1], -1) - setvarLB!(m, [-1.0,0.0,0.0]) optimize!(m) + end + end +end +""" @test status(m) == :Optimal @test isapprox(getobjval(m), 3, atol=eps) From 0c92ff43e9801ff99b67df656a9fb2b66612b8c0 Mon Sep 17 00:00:00 2001 From: Miles Lubin Date: Mon, 19 Jun 2017 17:08:35 -0400 Subject: [PATCH 71/83] another pass on attributes --- docs/src/apireference.md | 27 ++- src/SolverInterface/attributes.jl | 304 ++++++++++++++++++++++------- src/SolverInterface/constraints.jl | 2 + src/SolverInterface/nlp.jl | 4 +- 4 files changed, 256 insertions(+), 81 deletions(-) diff --git a/docs/src/apireference.md b/docs/src/apireference.md index 38bcce6..c262f5f 100644 --- a/docs/src/apireference.md +++ b/docs/src/apireference.md @@ -76,10 +76,12 @@ SOS2 ## Attributes -These are used to get and set properties of the model. +These are used to get and set properties of the model or solver. ```@docs -AbstractAttribute +AbstractSolverOrModelAttribute +AbstractVariableAttribute +AbstractConstraintAttribute cangetattribute getattribute getattribute! @@ -87,9 +89,17 @@ cansetattribute setattribute! ``` -### Scalar Attributes +### Solver or Model Attributes + +These attribute apply to solver or model objects, as noted. ```@docs +ReturnsDuals +SupportsAddConstraintAfterSolve +SupportsDeleteConstraint +SupportsAddVariableAfterSolver +SupportsQuadraticObjective +SupportsConicThroughQuadratic ObjectiveValue ObjectiveBound RelativeGap @@ -100,8 +110,10 @@ BarrierIterations NodeCount RawSolver ResultCount -VariableCount -ConstraintCount +NumberOfVariables +NumberOfVariablewiseConstraints +NumberOfAffineConstraints +NumberOfQuadraticConstraints SupportsVariablewiseConstraint SupportsAffineConstraint SupportsQuadraticConstraint @@ -112,7 +124,7 @@ DualStatus ### Variable Attributes -These attributes are associated with variables. Calls to `getattribute` and `setattribute!` should include as an argument a single `VariableReference` or a vector of `VariableReference` objects. +These attributes are associated with variables. Calls to `getattribute` and `setattribute!` should include as an argument a single `VariableReference` or a vector of `VariableReference` objects. By convention, the name of a variable attributes begins with `Variable`. ```@docs VariablePrimalStart @@ -128,7 +140,8 @@ VariableBasisStatus ### Constraint Attributes -These attributes are associated with constraints. Calls to `getattribute` and `setattribute!` should include as an argument a single `ConstraintReference` or a vector of `ConstriaintReference{T}` objects. +These attributes are associated with constraints. Calls to `getattribute` and `setattribute!` should include as an argument a single `ConstraintReference` or a vector of `ConstriaintReference{T}` objects. By convention, the name of a variable attributes begins with `Variable`. + ```@docs ConstraintPrimalStart diff --git a/src/SolverInterface/attributes.jl b/src/SolverInterface/attributes.jl index bd6a263..86963b3 100644 --- a/src/SolverInterface/attributes.jl +++ b/src/SolverInterface/attributes.jl @@ -1,15 +1,56 @@ """ - AbstractAttribute + AbstractSolverOrModelAttribute Abstract supertype for attribute objects that can be used -to set or get attributes (properties) of the model. +to set or get attributes (properties) +of the model or solver. """ -abstract type AbstractAttribute end +abstract type AbstractSolverOrModelAttribute end """ - getattribute(m::AbstractMathProgModel, attr::AbstractAttribute, extra_args...) + AbstractVariableAttribute -Return an attribute of the model `m` specified by attribute type `attr`. +Abstract supertype for attribute objects that can be used +to set or get attributes (properties) of variables in the model. +""" +abstract type AbstractVariableAttribute end + +""" + AbstractConstraintAttribute + +Abstract supertype for attribute objects that can be used +to set or get attributes (properties) of constraints in the model. +""" +abstract type AbstractConstraintAttribute end + +const AnyAttribute = Union{AbstractSolverOrModelAttribute,AbstractVariableAttribute,AbstractConstraintAttribute} + +""" + getattribute(s::AbstractMathProgSolver, attr::AbstractSolverOrModelAttribute) + +Return an attribute `attr` of the solver `s`. + + getattribute(m::AbstractMathProgModel, attr::AbstractSolverOrModelAttribute) + +Return an attribute `attr` of the model `m`. + + getattribute(m::AbstractMathProgModel, attr::AbstractVariableAttribute, v::VariableReference) + +Return an attribute `attr` of the variable `v` in model `m`. + + getattribute(m::AbstractMathProgModel, attr::AbstractVariableAttribute, v::Vector{VariableReference}) + +Return a vector of attributes corresponding to each variable in the collection `v` in the model `m`. + + getattribute(m::AbstractMathProgModel, attr::AbstractConstraintAttribute, c::ConstraintReference) + +Return an attribute `attr` of the constraint `c` in model `m`. + + getattribute(m::AbstractMathProgModel, attr::AbstractConstraintAttribute, c::Vector{VariablewiseConstraintReference{T}}) + getattribute(m::AbstractMathProgModel, attr::AbstractConstraintAttribute, c::Vector{AffineConstraintReference{T}}) + getattribute(m::AbstractMathProgModel, attr::AbstractConstraintAttribute, c::Vector{QuadraticConstraintReference{T}}) + +Return a vector of attributes corresponding to each constraint in the collection `c` in the model `m`. # Examples @@ -22,57 +63,161 @@ getattribute(m, OtherAttribute("something specific to cplex")) """ function getattribute end -function getattribute(m, attr::AbstractAttribute, args...) +function getattribute(m, attr::AnyAttribute, args...) throw(ArgumentError("Model of type $(typeof(m)) does not support accessing the attribute $attr")) end """ - getattribute!(output, m::AbstractMathProgModel, attr::AbstractAttribute, extra_args...) + getattribute!(output, m::AbstractMathProgModel, args...) -An in-place version of `getattribute`. Return an attribute of the model `m` specified by attribute type `attr` into output vector `attr`. +An in-place version of `getattribute`. The signature matches that of `getattribute` except that the the result is placed in the vector `output`. """ function getattribute! end -function getattribute!(output, m, attr::AbstractAttribute, args...) +function getattribute!(output, m, attr::AnyAttribute, args...) throw(ArgumentError("Model of type $(typeof(m)) does not support accessing the attribute $attr")) end """ - cangetattribute(m::AbstractMathProgModel, attr::AbstractAttribute)::Bool + cangetattribute(s::AbstractMathProgSolver, attr::AbstractSolverOrModelAttribute)::Bool + +Return a `Bool` indicating whether it is possible to query attribute `attr` from the solver `s`. + + cangetattribute(m::AbstractMathProgModel, attr::AbstractVariableAttribute, R::Type{VariableReference})::Bool + cangetattribute(m::AbstractMathProgModel, attr::AbstractConstraintAttribute, R::Type{VariablewiseConstraintReference{T})::Bool + cangetattribute(m::AbstractMathProgModel, attr::AbstractConstraintAttribute, R::Type{AffineConstraintReference{T})::Bool + cangetattribute(m::AbstractMathProgModel, attr::AbstractConstraintAttribute, R::Type{QuadraticConstraintReference{T})::Bool Return a `Bool` indicating whether the model `m` currently has a value for -the attributed specified by attribute type `attr`. +the attributed specified by attribute type `attr` applied to the reference type `R`. + +# Examples +```julia +cangetattribute(GurobiSolver(), SupportsAffineConstraint{Zero}()) +cangetattribute(m, ObjectiveValue()) +cangetattribute(m, VariablePrimalStart(), varref) +cangetattribute(m, ConstraintPrimal(), conref) """ function cangetattribute end -cangetattribute(m::AbstractMathProgModel, attr::AbstractAttribute) = false +cangetattribute(m::AbstractMathProgModel, attr::AnyAttribute) = false """ - cansetattribute(m::AbstractMathProgModel, attr::AbstractAttribute)::Bool + cansetattribute(s::AbstractMathProgSolver, attr::AbstractSolverOrModelAttribute)::Bool + +Return a `Bool` indicating whether it is possible to set attribute `attr` in the solver `s`. + + cansetattribute(m::AbstractMathProgModel, attr::AbstractVariableAttribute, R::Type{VariableReference})::Bool + cansetattribute(m::AbstractMathProgModel, attr::AbstractConstraintAttribute, R::Type{VariablewiseConstraintReference{T})::Bool + cangetattribute(m::AbstractMathProgModel, attr::AbstractConstraintAttribute, R::Type{AffineConstraintReference{T})::Bool + cangetattribute(m::AbstractMathProgModel, attr::AbstractConstraintAttribute, R::Type{QuadraticConstraintReference{T})::Bool -Return a `Bool` indicating whether the model `m` will accept a -`setattribute!` call for the attributed specified by attribute type `attr`. +Return a `Bool` indicating whether it is possible to set attribute `attr` applied to the reference type `R` in the model `m`. + +# Examples +```julia +cansetattribute(GurobiSolver(), SupportsAffineConstraint{Zero}()) +cansetattribute(m, ObjectiveValue()) +cansetattribute(m, VariablePrimalStart(), VariableReference) +cansetattribute(m, ConstraintPrimal(), AffineConstraintReference{NonNegative}) """ function cansetattribute end -cansetattribute(m::AbstractMathProgModel, attr::AbstractAttribute) = false +cansetattribute(m::AbstractMathProgModel, attr::AnyAttribute) = false """ - setattribute!(m::AbstractMathProgModel, attr::AbstractAttribute, ...) + setattribute!(s::AbstractMathProgSolver, attr::AbstractSolverOrModelAttribute, value) + +Assign `value` to the attribute `attr` of the solver `s`. + + setattribute!(m::AbstractMathProgModel, attr::AbstractSolverOrModelAttribute, value) + +Assign `value` to the attribute `attr` of the model `m`. + + setattribute!(m::AbstractMathProgModel, attr::AbstractVariableAttribute, v::VariableReference, value) + +Assign `value` to the attribute `attr` of variable `v` in model `m`. + + setattribute!(m::AbstractMathProgModel, attr::AbstractVariableAttribute, v::Vector{VariableReference}, vector_of_values) + +Assign a value respectively to the attribute `attr` of each variable in the collection `v` in model `m`. + + setattribute!(m::AbstractMathProgModel, attr::AbstractConstraintAttribute, c::ConstraintReference, value) -Set an attribute of the model `m` specified by attribute type `attr`. +Assign a value to the attribute `attr` of constraint `c` in model `m`. + + setattribute!(m::AbstractMathProgModel, attr::AbstractConstraintAttribute, c::Vector{VariablewiseConstraintReference{T}}) + setattribute!(m::AbstractMathProgModel, attr::AbstractConstraintAttribute, c::Vector{AffineConstraintReference{T}}) + setattribute!(m::AbstractMathProgModel, attr::AbstractConstraintAttribute, c::Vector{QuadraticConstraintReference{T}}) + +Assign a value respectively to the attribute `attr` of each constraint in the collection `c` in model `m`. """ function setattribute! end -function setattribute!(m, attr::AbstractAttribute, args...) +function setattribute!(m, attr::AnyAttribute, args...) throw(ArgumentError("Model of type $(typeof(m)) does not support setting the attribute $attr")) end -# Scalar attributes +# Solver or model attributes + +""" + ReturnsDuals() + +A `Bool` indicating if the solver should be expected to return dual +solutions when appropriate. A solver attribute. +""" +struct ReturnsDuals <: AbstractSolverOrModelAttribute end + +""" + SupportsAddConstraintAfterSolver() + +A `Bool` indicating if the solver supports adding constraints +after a solve. If `false`, then a new model should be constructed instead. +A solver attribute. +""" +struct SupportsAddConstraintAfterSolve <: AbstractSolverOrModelAttribute end + +""" + SupportsDeleteConstraint() + +A `Bool` indicating if the solver supports deleting constraints +from a model. A solver attribute. +""" +struct SupportsDeleteConstraint <: AbstractSolverOrModelAttribute end + +""" + SupportsAddVariableAfterSolve() + +A `Bool` indicating if the solver supports adding variables +after a solve. In the context of linear programming, +this is known as column generation. A solver attribute. +""" +struct SupportsAddVariableAfterSolver <: AbstractSolverOrModelAttribute end + +# TODO: solver-independent parameters + +# TODO: supports modify objective + +""" + SupportsQuadraticObjective() + +A `Bool` indicating if the solver supports quadratic objectives. +A solver attribute. +""" +struct SupportsQuadraticObjective <: AbstractSolverOrModelAttribute end + +""" + SupportsConicThroughQuadratic() + +A `Bool` indicating if the solver interprets certain quadratic constraints +as second-order cone constraints. A solver attribute. +""" +struct SupportsConicThroughQuadratic <: AbstractSolverOrModelAttribute end + """ ObjectiveValue(resultidx::Int=1, objectiveindex::Int=1) -The objective value of the `resultindex`'th primal result of the `objectiveindex`'th objective. +The objective value of the `resultindex`'th primal result of the `objectiveindex`'th objective. A model attribute. Both `resultindex` and `objectiveindex` default to 1. """ -struct ObjectiveValue <: AbstractAttribute +struct ObjectiveValue <: AbstractSolverOrModelAttribute resultindex::Int objectiveindex::Int (::Type{ObjectiveValue})(resultindex=1, objectiveindex=1) = new(resultindex, objectiveindex) @@ -81,108 +226,123 @@ end """ ObjectiveBound() -The best known bound on the optimal objective value. +The best known bound on the optimal objective value. A model attribute. """ -struct ObjectiveBound <: AbstractAttribute end +struct ObjectiveBound <: AbstractSolverOrModelAttribute end """ RelativeGap() -The final relative optimality gap as optimization terminated. That is, ``\\frac{|b-f|}{|f|}``, where ``b`` is the best bound and ``f`` is the best feasible objective value. +The final relative optimality gap as optimization terminated. That is, ``\\frac{|b-f|}{|f|}``, where ``b`` is the best bound and ``f`` is the best feasible objective value. A model attribute. """ -struct RelativeGap <: AbstractAttribute end +struct RelativeGap <: AbstractSolverOrModelAttribute end """ SolveTime() -The total elapsed solution time (in seconds) as reported by the solver. +The total elapsed solution time (in seconds) as reported by the solver. A model attribute. """ -struct SolveTime <: AbstractAttribute end +struct SolveTime <: AbstractSolverOrModelAttribute end """ Sense() -The optimization sense of the model, an `OptimizationSense` with value `MinSense` or `MaxSense`. +The optimization sense of the model, an `OptimizationSense` with value `MinSense` or `MaxSense`. A model attribute. """ -struct Sense <: AbstractAttribute end +struct Sense <: AbstractSolverOrModelAttribute end @enum OptimizationSense MinSense MaxSense """ SimplexIterations() -The cumulative number of simplex iterations during the optimization process. In particular, for a MIP the total simplex iterations for all nodes. +The cumulative number of simplex iterations during the optimization process. In particular, for a MIP the total simplex iterations for all nodes. A model attribute. """ -struct SimplexIterations <: AbstractAttribute end +struct SimplexIterations <: AbstractSolverOrModelAttribute end """ BarrierIterations() -The cumulative number of barrier iterations during the optimization process. +The cumulative number of barrier iterations during the optimization process. A model attribute. """ -struct BarrierIterations <: AbstractAttribute end +struct BarrierIterations <: AbstractSolverOrModelAttribute end """ NodeCount() -The total number of branch-and-bound nodes explored. +The total number of branch-and-bound nodes explored. A model attribute. """ -struct NodeCount <: AbstractAttribute end +struct NodeCount <: AbstractSolverOrModelAttribute end """ RawSolver() -An object that may be used to access a solver-specific API for this model. +An object that may be used to access a solver-specific API for this model. A model attribute. """ -struct RawSolver <: AbstractAttribute end +struct RawSolver <: AbstractSolverOrModelAttribute end """ ResultCount() -The number of results available. +The number of results available. A model attribute. """ -struct ResultCount <: AbstractAttribute end +struct ResultCount <: AbstractSolverOrModelAttribute end """ - VariableCount() + NumberOfVariables() -The number of variables in the model. +The number of variables in the model. A model attribute. """ -struct VariableCount <: AbstractAttribute end +struct NumberOfVariables <: AbstractSolverOrModelAttribute end """ - ConstraintCount{T}() + NumberOfVariablewiseConstraints{T}() -The number of constraints of type T in the model. +The number of variablewise constraints of type T in the model. A model attribute. """ -struct ConstraintCount{T} <: AbstractAttribute end +struct NumberOfVariablewiseConstraints{T} <: AbstractSolverOrModelAttribute end + +""" + NumberOfAffineConstraints{T}() + +The number of affine constraints of type T in the model. A model attribute. +""" +struct NumberOfAffineConstraints{T} <: AbstractSolverOrModelAttribute end + +""" + NumberOfQuadraticConstraints{T}() + +The number of quadratic constraints of type T in the model. A model attribute. +""" +struct NumberOfQuadraticConstraints{T} <: AbstractSolverOrModelAttribute end + """ SupportsVariablewiseConstraint{T}() A `Bool` indicating whether the solver or model supports a variablewise constraint in the set ``S`` which -is a set of type `T`. +is a set of type `T`. A solver and model attribute. """ -struct SupportsVariablewiseConstraint{T} <: AbstractAttribute end +struct SupportsVariablewiseConstraint{T} <: AbstractSolverOrModelAttribute end """ SupportsAffineConstraint{T}() A `Bool` indicating whether the solver or model supports a constraint of of the form "affine expression" in ``S`` where ``S`` -is a set of type `T`. +is a set of type `T`. A solver and model attribute. """ -struct SupportsAffineConstraint{T} <: AbstractAttribute end +struct SupportsAffineConstraint{T} <: AbstractSolverOrModelAttribute end """ SupportsQuadraticConstraint{T}() A `Bool` indicating whether the solver or model supports a constraint of of the form "quadratic expression" in ``S`` where ``S`` -is a set of type `T`. +is a set of type `T`. A solver and model attribute. """ -struct SupportsQuadraticConstraint{T} <: AbstractAttribute end +struct SupportsQuadraticConstraint{T} <: AbstractSolverOrModelAttribute end @@ -194,7 +354,7 @@ struct SupportsQuadraticConstraint{T} <: AbstractAttribute end An initial assignment of the variables that the solver may use to warm-start the solve. """ -struct VariablePrimalStart <: AbstractAttribute end +struct VariablePrimalStart <: AbstractVariableAttribute end """ VariableLowerBoundDualStart() @@ -202,7 +362,7 @@ struct VariablePrimalStart <: AbstractAttribute end An initial assignment of the variable lower-bound duals that the solver may use to warm-start the solve. """ -struct VariableLowerBoundDualStart <: AbstractAttribute end +struct VariableLowerBoundDualStart <: AbstractVariableAttribute end """ VariableUpperBoundDualStart() @@ -210,21 +370,21 @@ struct VariableLowerBoundDualStart <: AbstractAttribute end An initial assignment of the variable upper-bound duals that the solver may use to warm-start the solve. """ -struct VariableUpperBoundDualStart <: AbstractAttribute end +struct VariableUpperBoundDualStart <: AbstractVariableAttribute end """ VariableLowerBound() Lower-bound constraints on variables. `-Inf` is valid as no bound. """ -struct VariableLowerBound <: AbstractAttribute end +struct VariableLowerBound <: AbstractVariableAttribute end """ VariableUpperBound() Upper-bound constraints for the variables. `Inf` is valid as no bound. """ -struct VariableUpperBound <: AbstractAttribute end +struct VariableUpperBound <: AbstractVariableAttribute end """ VariablePrimal(N) @@ -232,7 +392,7 @@ struct VariableUpperBound <: AbstractAttribute end The assignment to the primal variables in result `N`. If `N` is omitted, it is 1 by default. """ -struct VariablePrimal <: AbstractAttribute +struct VariablePrimal <: AbstractVariableAttribute N::Int end VariablePrimal() = VariablePrimal(1) @@ -242,7 +402,7 @@ VariablePrimal() = VariablePrimal(1) The assignment to the duals on the variable lower bounds in result `N`. If `N` is omitted, it is interpreted as 1. """ -struct VariableLowerBoundDual <: AbstractAttribute +struct VariableLowerBoundDual <: AbstractVariableAttribute N::Int end VariableLowerBoundDual() = VariableLowerBoundDual(1) @@ -252,7 +412,7 @@ VariableLowerBoundDual() = VariableLowerBoundDual(1) The assignment to the duals on the variable upper bounds in result `N`. If `N` is omitted, it is interpreted as 1. """ -struct VariableUpperBoundDual <: AbstractAttribute +struct VariableUpperBoundDual <: AbstractVariableAttribute N::Int end VariableUpperBoundDual() = VariableUpperBoundDual(1) @@ -262,7 +422,7 @@ VariableUpperBoundDual() = VariableUpperBoundDual(1) Returns the `BasisStatusCode` of a given variable, with respect to an available optimal solution basis. """ -struct VariableBasisStatus <: AbstractAttribute end +struct VariableBasisStatus <: AbstractVariableAttribute end """ BasisStatusCode @@ -284,7 +444,7 @@ An Enum of possible values for the `VariableBasisStatus` and `ConstraintBasisSta An initial assignment of the constraint primal values that the solver may use to warm-start the solve. """ -struct ConstraintPrimalStart <: AbstractAttribute end +struct ConstraintPrimalStart <: AbstractConstraintAttribute end """ ConstraintDualStart() @@ -292,7 +452,7 @@ struct ConstraintPrimalStart <: AbstractAttribute end An initial assignment of the constriant duals that the solver may use to warm-start the solve. """ -struct ConstraintDualStart <: AbstractAttribute end +struct ConstraintDualStart <: AbstractConstraintAttribute end """ ConstraintPrimal(N) @@ -300,7 +460,7 @@ struct ConstraintDualStart <: AbstractAttribute end The assignment to the constraint primal values in result `N`. If `N` is omitted, it is 1 by default. """ -struct ConstraintPrimal <: AbstractAttribute +struct ConstraintPrimal <: AbstractConstraintAttribute N::Int end ConstraintPrimal() = ConstraintPrimal(1) @@ -311,7 +471,7 @@ ConstraintPrimal() = ConstraintPrimal(1) The assignment to the constraint dual values in result `N`. If `N` is omitted, it is 1 by default. """ -struct ConstraintDual <: AbstractAttribute +struct ConstraintDual <: AbstractConstraintAttribute N::Int end ConstraintDual() = ConstraintDual(1) @@ -321,7 +481,7 @@ ConstraintDual() = ConstraintDual(1) Returns the `BasisStatusCode` of a given constraint, with respect to an available optimal solution basis. """ -struct ConstraintBasisStatus <: AbstractAttribute end +struct ConstraintBasisStatus <: AbstractConstraintAttribute end @@ -330,9 +490,9 @@ struct ConstraintBasisStatus <: AbstractAttribute end """ TerminationStatus() -A `TerminationStatusCode` explaining why the solver stopped. +A `TerminationStatusCode` explaining why the solver stopped. A model attribute. """ -struct TerminationStatus <: AbstractAttribute end +struct TerminationStatus <: AbstractSolverOrModelAttribute end """ TerminationStatusCode @@ -392,9 +552,9 @@ An Enum of possible values for the `PrimalStatus` and `DualStatus` attributes. T PrimalStatus(N) PrimalStatus() -The `ResultStatusCode` of the primal result `N`. If `N` is omitted, it defaults to 1. +The `ResultStatusCode` of the primal result `N`. If `N` is omitted, it defaults to 1. A model attribute. """ -struct PrimalStatus <: AbstractAttribute +struct PrimalStatus <: AbstractSolverOrModelAttribute N::Int end PrimalStatus() = PrimalStatus(1) @@ -403,9 +563,9 @@ PrimalStatus() = PrimalStatus(1) DualStatus(N) DualStatus() -The `ResultStatusCode` of the dual result `N`. If `N` is omitted, it defaults to 1. +The `ResultStatusCode` of the dual result `N`. If `N` is omitted, it defaults to 1. A model attribute. """ -struct DualStatus <: AbstractAttribute +struct DualStatus <: AbstractSolverOrModelAttribute N::Int end DualStatus() = DualStatus(1) diff --git a/src/SolverInterface/constraints.jl b/src/SolverInterface/constraints.jl index 7542450..022e609 100644 --- a/src/SolverInterface/constraints.jl +++ b/src/SolverInterface/constraints.jl @@ -60,6 +60,8 @@ where `varref` is a vector of variable references to specifiy the subset of the """ function addconstraint! end +# TODO: method to query if solver supports this type of modification + """ modifyconstraint!(m::AbstractMathProgModel, c::ConstraintReference, i::Int, args...) diff --git a/src/SolverInterface/nlp.jl b/src/SolverInterface/nlp.jl index b604135..c3f1ed4 100644 --- a/src/SolverInterface/nlp.jl +++ b/src/SolverInterface/nlp.jl @@ -12,7 +12,7 @@ export AbstractNLPEvaluator The assignment to the NLP constraint dual values in result `N`. If `N` is omitted, it is 1 by default. """ -struct ConstraintNLPDual <: AbstractAttribute +struct ConstraintNLPDual <: AbstractConstraintAttribute N::Int end ConstraintNLPDual() = ConstraintNLPDual(1) @@ -24,7 +24,7 @@ ConstraintNLPDual() = ConstraintNLPDual(1) An initial assignment of the NLP constriant duals that the solver may use to warm-start the solve. """ -struct ConstraintNLPDualStart <: AbstractAttribute end +struct ConstraintNLPDualStart <: AbstractConstraintAttribute end ### methods for AbstractNLPEvaluator ### From 76436361f2e013f4ac68fed23f32529a95e69738 Mon Sep 17 00:00:00 2001 From: Joaquim Dias Garcia Date: Mon, 19 Jun 2017 17:10:35 -0400 Subject: [PATCH 72/83] More tests (#192) --- test/linproginterface.jl | 275 ++++++++++++++++++++++++++------------- 1 file changed, 183 insertions(+), 92 deletions(-) diff --git a/test/linproginterface.jl b/test/linproginterface.jl index e31ab51..f152182 100644 --- a/test/linproginterface.jl +++ b/test/linproginterface.jl @@ -61,7 +61,7 @@ function linprogsolvertest(solver::AbstractMathProgSolver, eps = Base.rtoldefaul MPB.setattribute!(m, MPB.Sense(), MPB.MinSense) - MPB.setobjective!(m, 1, 0.0, v, [-1.0, 0.0]) + MPB.setobjective!(m, 0.0, v, [-1.0, 0.0]) # TODO: query objective # (b, a_varref, a_coef, qi, qj, qc) = MPB.getobjective(m) @@ -82,29 +82,31 @@ function linprogsolvertest(solver::AbstractMathProgSolver, eps = Base.rtoldefaul test_result(m, v, c, MPB.Success, MPB.FeasiblePoint, MPB.FeasiblePoint, 1, [1.0, 0.0], [0.0, -1.0], [0.0, 0.0], [1.0], [1.0]) + end + end +end +""" # add new variable to get: # max x + 2z # s.t. x + y + z <= 1 # x,y,z >= 0 - z = MPB.addvariable!(m, c, [1]) - MPB.setattribute!(m, MPB.VariableLowerBound(), z, 0) - MPB.modifyobjective!(m, z, 2) + addvar!(m, [1], [1.0], 0, Inf, 2.0) - @test MPB.getattribute(m, MPB.VariableCount()) == 3 - @test MPB.getattribute(m, MPB.ConstraintCount()) == 1 + @test numvar(m) == 3 + @test numconstr(m) == 1 optimize!(m) - test_result(m, v, c, MPB.Success, MPB.FeasiblePoint, MPB.FeasiblePoint, 2, [0.0, 0.0, 1.0], [-1.0, -2.0, 0.0], [0.0, 0.0, 0.0], [1.0], [2.0]) - - MPB.setattribute!(m, MPB.VariableLowerBound(), v[1], -1) + @test status(m) == :Optimal + @test isapprox(getobjval(m), 2, atol=eps) + @test isapprox(norm(getsolution(m) - [0.0, 0.0, 1.0]), 0.0, atol=eps) + @test isapprox(getconstrsolution(m)[1], 1.0, atol=eps) + @test isapprox(getconstrduals(m)[1], 2.0, atol=eps) + @test isapprox(norm(getreducedcosts(m) - [-1.0, -2.0, 0.0]), 0.0, atol=eps) + setvarLB!(m, [-1.0,0.0,0.0]) optimize!(m) - end - end -end -""" @test status(m) == :Optimal @test isapprox(getobjval(m), 3, atol=eps) @@ -143,35 +145,53 @@ end @test isapprox(norm(getreducedcosts(m) - [0.0, 0.0, -1.5]), 0.0, atol=eps) end +""" +function linprogsolvertest2(solver::AbstractMathProgSolver, eps = Base.rtoldefault(Float64)) + @testset "Testing LP interface with $solver part 2" begin @testset "addvar! interface" begin m = LinearQuadraticModel(solver) # Min -x # s.t. x + y <= 1 # x, y >= 0 - addvar!(m, 0, Inf, -1) - addvar!(m, 0, Inf, 0) - addconstr!(m, [1, 2], [1.0, 1.0], -Inf, 1.0) - @test numvar(m) == 2 - @test numconstr(m) == 1 - @test getvarLB(m) == [0.,0.] - @test getvarUB(m)[1] >= 1e20 - @test getvarUB(m)[2] >= 1e20 - @test getconstrLB(m)[1] <= -1e20 - @test getconstrUB(m)[1] == 1.0 - @test getobj(m) == [-1.,0.] - @test getsense(m) == :Min + m = MPB.Model(solver) + + x = MPB.addvariable!(m) + y = MPB.addvariable!(m) + + MPB.setattribute!(m, MPB.VariableLowerBound(), [x, y], [0, 0]) + + c = MPB.addconstraint!(m, -1, [x, y], [1.0, 1.0], MPB.NonPositive(1)) + + MPB.setattribute!(m, MPB.Sense(), MPB.MinSense) + MPB.setobjective!(m, 0.0, x, -1.0) + + @test MPB.getattribute(m, MPB.VariableCount()) == 2 + @test MPB.getattribute(m, MPB.ConstraintCount()) == 1 + + # getters #190 + # @test getvarLB(m) == [0.,0.] + # @test getvarUB(m)[1] >= 1e20 + # @test getvarUB(m)[2] >= 1e20 + # @test getconstrLB(m)[1] <= -1e20 + # @test getconstrUB(m)[1] == 1.0 + # @test getobj(m) == [-1.,0.] + # @test getsense(m) == :Min optimize!(m) - @test status(m) == :Optimal - @test isapprox(getobjval(m), -1, atol=eps) - @test isapprox(norm(getsolution(m) - [1.0, 0.0]), 0.0, atol=eps) - @test isapprox(getconstrsolution(m)[1], 1.0, atol=eps) - @test isapprox(getconstrduals(m)[1], -1.0, atol=eps) - @test isapprox(norm(getreducedcosts(m) - [0.0, 1.0]), 0.0, atol=eps) - end + @test MPB.getattribute(m, MPB.TerminationStatus()) == :Success + @test MPB.getattribute(m, MPB.PrimalStatus()) == MPB.FeasiblePoint + @test MPB.getattribute(m, MPB.DualStatus()) == MPB.FeasiblePoint + + @test isapprox(MPB.getattribute(m, MPB.ObjectiveValue()), -1.0, atol=eps) + @test isapprox(MPB.getattribute(m, MPB.VariablePrimal(), [x, y]), [1.0, 0.0], atol=eps) + + @test isapprox(MPB.getattribute(m, MPB.ConstraintPrimal()), 0.0, atol=eps) + @test isapprox(MPB.getattribute(m, MPB.ConstraintDual()), -1.0, atol=eps) + @test isapprox(MPB.getattribute(m, MPB.VariableDual(), [x, y]), [0.0, 1.0], atol=eps) + end @testset "setconstrLB! and setconstrUB!" begin #################################### @@ -182,67 +202,100 @@ end # Setting upper and lower bound to same value works # - m = LinearQuadraticModel(solver) + m = MPB.Model(solver) + + x = MPB.addvariable!(m) + y = MPB.addvariable!(m) + # Min x - y - # s.t. 0.0 <= x - # y <= 0.0 + # s.t. 0.0 <= x (c1) + # y <= 0.0 (c2) # x,y unbounded + c1 = MPB.addconstraint!(m, 0.0, x, [1.0, 0.0], MPB.NonNegative(1)) + c2 = MPB.addconstraint!(m, 0.0, y, [0.0, 1.0], MPB.NonPositive(1)) + + MPB.setattribute!(m, MPB.Sense(), MPB.MinSense) - loadproblem!(m, [ 1.0 0.0 ; 0.0 1.0 ], [-Inf, -Inf], [Inf,Inf], [1.0, -1.0], [0.0,-Inf], [Inf,0.0], :Min) + MPB.setobjective!(m, 0.0, [x, y], [1.0, -1.0]) - optimize!(m) + MPB.optimize!(m) - @test status(m) == :Optimal - @test isapprox(getobjval(m), 0.0, atol=eps) - @test isapprox(norm(getsolution(m)), 0.0, atol=eps) + @test MPB.getattribute(m, MPB.TerminationStatus()) == :Success + @test MPB.getattribute(m, MPB.PrimalStatus()) == MPB.FeasiblePoint + @test MPB.getattribute(m, MPB.DualStatus()) == MPB.FeasiblePoint + @test isapprox(MPB.getattribute(m, MPB.ObjectiveValue()), 0.0, atol=eps) + @test isapprox(MPB.getattribute(m, MPB.VariablePrimal(), [x, y]), [0.0, 0.0], atol=eps) # Min x - y - # s.t. 100.0 <= x + # s.t. 100.0 <= x or -100 + x \in NonNegative # y <= 0.0 # x,y unbounded - setconstrLB!(m,[100.0,-Inf]) + modifyconstraint!(m, c1, 1, -100.0) optimize!(m) - @test status(m) == :Optimal - @test isapprox(getobjval(m), 100.0, atol=eps) - @test isapprox(norm(getsolution(m) - [ 100.0, 0.0 ]), 0.0, atol=eps) + @test MPB.getattribute(m, MPB.TerminationStatus()) == :Success + @test MPB.getattribute(m, MPB.PrimalStatus()) == MPB.FeasiblePoint + @test MPB.getattribute(m, MPB.DualStatus()) == MPB.FeasiblePoint + @test isapprox(MPB.getattribute(m, MPB.ObjectiveValue()), 100.0, atol=eps) + @test isapprox(MPB.getattribute(m, MPB.VariablePrimal(), [x, y]), [100.0, 0.0], atol=eps) # Min x - y # s.t. 100.0 <= x # y <= -100.0 # x,y unbounded - setconstrUB!(m,[Inf,-100.0]) + modifyconstraint!(m, c2, 1, 100.0) optimize!(m) - @test status(m) == :Optimal - @test isapprox(getobjval(m), 200.0, atol=eps) - @test isapprox(norm(getsolution(m) - [ 100.0, -100.0 ]), 0.0, atol=eps) + @test MPB.getattribute(m, MPB.TerminationStatus()) == :Success + @test MPB.getattribute(m, MPB.PrimalStatus()) == MPB.FeasiblePoint + @test MPB.getattribute(m, MPB.DualStatus()) == MPB.FeasiblePoint + @test isapprox(MPB.getattribute(m, MPB.ObjectiveValue()), 200.0, atol=eps) + @test isapprox(MPB.getattribute(m, MPB.VariablePrimal(), [x, y]), [100.0, -100.0], atol=eps) end @testset "Issue #40 from Gurobi.jl" begin # Test issue #40 from Gurobi.jl # min x - # s.t. x >= 0 - # x >= 3 - m = LinearQuadraticModel(solver) - loadproblem!(m, [1.0 1.0]', [-Inf], [Inf], [1.0], [0.0, 3.0], [Inf, Inf], :Min) - optimize!(m) - for i = 1:length(getconstrLB(m)) - @test getconstrLB(m)[i] <= getconstrsolution(m)[i] + eps - @test getconstrsolution(m)[i] <= getconstrUB(m)[i] + eps + # s.t. x >= 0 (c1) + # x >= 3 (c2) + + m = MPB.Model(solver) + + x = MPB.addvariable!(m) + + c = MPB.addconstraint!(m, [0.0 -3.0], [x x], [1.0 1.0], MPB.NonNegative(2)) + + MPB.setattribute!(m, MPB.Sense(), MPB.MinSense) + + MPB.setobjective!(m, 0.0, [x], [1.0]) + + MPB.optimize!(m) + + for i = 1:MPB.getattribute(m, MPB.ConstraintCount()) + # Get Bounds #190 + # @test getconstrLB(m)[i] <= getconstrsolution(m)[i] + eps + # @test getconstrsolution(m)[i] <= getconstrUB(m)[i] + eps end # min x # s.t. x <= 0 # x <= 3 - m = LinearQuadraticModel(solver) - loadproblem!(m, [1.0 1.0]', [-Inf], [Inf], [1.0], [-Inf, -Inf], [0.0, 3.0], :Max) - optimize!(m) - for i = 1:length(getconstrLB(m)) - @test getconstrLB(m)[i] <= getconstrsolution(m)[i] + eps - @test getconstrsolution(m)[i] <= getconstrUB(m)[i] + eps + m = MPB.Model(solver) + + x = MPB.addvariable!(m) + + c = MPB.addconstraint!(m, [0.0 -3.0], [x x], [1.0 1.0], MPB.NonPositive(2)) + + MPB.setattribute!(m, MPB.Sense(), MPB.MinSense) + + MPB.setobjective!(m, 0.0, [x], [1.0]) + + MPB.optimize!(m) + for i = 1:MPB.getattribute(m, MPB.ConstraintCount()) + # Get Bounds #190 + # @test getconstrLB(m)[i] <= getconstrsolution(m)[i] + eps + # @test getconstrsolution(m)[i] <= getconstrUB(m)[i] + eps end end - @testset "Change coeffs, del constr, del var" begin ##################################### # Start from simple LP @@ -254,29 +307,48 @@ end # maximize x + y # - # s.t. 2 x + 1 y <= 4 - # 1 x + 2 y <= 4 + # s.t. 2 x + 1 y <= 4 (c1) + # 1 x + 2 y <= 4 (c2) # x >= 0, y >= 0 # # solution: x = 1.3333333, y = 1.3333333, objv = 2.66666666 - m = LinearQuadraticModel(solver) + m = MPB.Model(solver) - loadproblem!(m, [ 2.0 1.0 ; 1.0 2.0 ], [0.0,0.0], [Inf,Inf], [1.0, 1.0], [-Inf, -Inf], [4.0,4.0], :Max) + v = MPB.addvariables!(m, 2) + + MPB.setattribute!(m, MPB.VariableLowerBound(), v, [0, 0]) - optimize!(m) - @test status(m) == :Optimal - @test isapprox(getobjval(m), 2.6666666666, atol=eps) - @test isapprox(norm(getsolution(m) - [1.3333333333, 1.3333333333]), 0.0, atol=eps) + c1 = MPB.addconstraint!(m, -4, v, [2, 1], MPB.NonPositive(1)) + c2 = MPB.addconstraint!(m, -4, v, [1, 2], MPB.NonPositive(1)) - # copy and solve again + MPB.setattribute!(m, MPB.Sense(), MPB.MaxSense) + + MPB.setobjective!(m, 0.0, v, [1.0, 1.0]) + + MPB.optimize!(m) + + @test MPB.getattribute(m, MPB.TerminationStatus()) == :Success + @test MPB.getattribute(m, MPB.PrimalStatus()) == MPB.FeasiblePoint + @test MPB.getattribute(m, MPB.DualStatus()) == MPB.FeasiblePoint - if applicable(copy, m) + @test isapprox(MPB.getattribute(m, MPB.ObjectiveValue()), 2.6666666666, atol=eps) + + @test isapprox(MPB.getattribute(m, MPB.VariablePrimal(), v), [1.3333333333, 1.3333333333], atol=eps) + + # copy and solve again + + if applicable(copy, m) # see 188 m2 = copy(m) + optimize!(m2) - @test status(m2) == :Optimal - @test isapprox(getobjval(m2), 2.6666666666, atol=eps) - @test isapprox(norm(getsolution(m2) - [1.3333333333, 1.3333333333]), 0.0, atol=eps) + + @test MPB.getattribute(m, MPB.TerminationStatus()) == :Success + @test MPB.getattribute(m, MPB.PrimalStatus()) == MPB.FeasiblePoint + @test MPB.getattribute(m, MPB.DualStatus()) == MPB.FeasiblePoint + + @test isapprox(MPB.getattribute(m, MPB.ObjectiveValue()), 2.6666666666, atol=eps) + @test isapprox(MPB.getattribute(m, MPB.VariablePrimal(), v), [1.3333333333, 1.3333333333], atol=eps) end @@ -289,11 +361,18 @@ end # # solution: x = 0, y = 2, objv = 2 if applicable(changecoeffs!, m, [1], [2], [2.]) - changecoeffs!(m, [1], [2], [2.]) + modifyconstraint!(m, c1, v[2], 2.0) optimize!(m) - @test status(m) == :Optimal - @test isapprox(getobjval(m), 2.0, atol=eps) - @test isapprox(norm(getsolution(m) - [0.0, 2.0]), 0.0, atol=eps) + + MPB.optimize!(m) + + @test MPB.getattribute(m, MPB.TerminationStatus()) == :Success + @test MPB.getattribute(m, MPB.PrimalStatus()) == MPB.FeasiblePoint + @test MPB.getattribute(m, MPB.DualStatus()) == MPB.FeasiblePoint + + @test isapprox(MPB.getattribute(m, MPB.ObjectiveValue()), 2.0, atol=eps) + + @test isapprox(MPB.getattribute(m, MPB.VariablePrimal(), v), [0.0, 2.0], atol=eps) end @@ -304,12 +383,18 @@ end # x >= 0, y >= 0 # # solution: x = 4, y = 0, objv = 4 - if applicable(delconstrs!, m, [1]) - delconstrs!(m, [1]) + if applicable(delete!, m, [1]) + delete!(m, c1) + optimize!(m) - @test status(m) == :Optimal - @test isapprox(getobjval(m), 4.0, atol=eps) - @test isapprox(norm(getsolution(m) - [4.0, 0.0]), 0.0, atol=eps) + + @test MPB.getattribute(m, MPB.TerminationStatus()) == :Success + @test MPB.getattribute(m, MPB.PrimalStatus()) == MPB.FeasiblePoint + @test MPB.getattribute(m, MPB.DualStatus()) == MPB.FeasiblePoint + + @test isapprox(MPB.getattribute(m, MPB.ObjectiveValue()), 4.0, atol=eps) + + @test isapprox(MPB.getattribute(m, MPB.VariablePrimal(), v), [4.0, 0.0], atol=eps) end # delvars and solve @@ -319,18 +404,24 @@ end # y >= 0 # # solution: y = 2, objv = 2 - if applicable(delvars!, m, [1]) - delvars!(m, [1]) + if applicable(delete!, m, [1]) + delete!(m, v[1]) + optimize!(m) - @test status(m) == :Optimal - @test isapprox(getobjval(m), 2.0, atol=eps) - @test isapprox(getsolution(m)[1], 2.0, atol=eps) + + @test MPB.getattribute(m, MPB.TerminationStatus()) == :Success + @test MPB.getattribute(m, MPB.PrimalStatus()) == MPB.FeasiblePoint + @test MPB.getattribute(m, MPB.DualStatus()) == MPB.FeasiblePoint + + @test isapprox(MPB.getattribute(m, MPB.ObjectiveValue()), 2.0, atol=eps) + + @test isapprox(MPB.getattribute(m, MPB.VariablePrimal(), v[2]), 2.0, atol=eps) end end end end - +""" function linprogsolvertestextra(solver::AbstractMathProgSolver; eps = Base.rtoldefault(Float64)) @testset "Testing LP interface extra with $solver" begin From c6f3838cc921b7188cf3799b7d00f9cf8f0533ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Legat?= Date: Sat, 24 Jun 2017 03:39:28 +0200 Subject: [PATCH 73/83] Add the PSD cone (#194) --- docs/src/apireference.md | 2 ++ src/SolverInterface/sets.jl | 51 ++++++++++++++++++++++++++++++++++++- 2 files changed, 52 insertions(+), 1 deletion(-) diff --git a/docs/src/apireference.md b/docs/src/apireference.md index c262f5f..d10e2ee 100644 --- a/docs/src/apireference.md +++ b/docs/src/apireference.md @@ -68,6 +68,8 @@ NonPositive Zero Interval SecondOrderCone +PositiveSemidefiniteConeTriangle +PositiveSemidefiniteConeScaled Integers Binaries SOS1 diff --git a/src/SolverInterface/sets.jl b/src/SolverInterface/sets.jl index 160b289..a570e18 100644 --- a/src/SolverInterface/sets.jl +++ b/src/SolverInterface/sets.jl @@ -60,7 +60,56 @@ struct SecondOrderCone <: AbstractSet end #ExponentialCone -#PositiveSemidefiniteCone + +""" + PositiveSemidefiniteConeTriangle(n) + +The cone of symmetric ``n \\times n`` matrices that are positive semidefinite. +The dimension of the cone is ``n(n+1)/2`` since the matrices are symmetric. +The entries of the upper triangular part of the matrix are given row by row (or equivalently, the entries of the lower triangular part are given column by column). +The scalar product is the sum of the pairwise product of the diagonal entries plus twice the sum of the pairwise product of the upper diagonal entries. + +### Examples + +The matrix +```math +\\begin{bmatrix} + 1 & 2 & 3\\\\ + 2 & 4 & 5\\\\ + 3 & 5 & 6 +\\end{bmatrix} +``` +corresponds to ``(1, 2, 3, 4, 5, 6)`` for `PositiveSemidefiniteConeTriangle` +""" +struct PositiveSemidefiniteConeTriangle <: AbstractSet + dim::Int +end + +""" + PositiveSemidefiniteConeScaled(n) + +The cone of symmetric ``n \\times n`` matrices that are positive semidefinite. +The dimension of the cone is ``n(n+1)/2`` since the matrices are symmetric. +The entries of the upper triangular part of the matrix are given row by row (or equivalently, the entries of the lower triangular part are given column by column). +The off-diagonal entries of the matrices of both the cone and its dual are scaled by ``\\sqrt{2}`` and the scalar product is simply the sum of the pairwise product of the entries. + +### Examples + +The matrix +```math +\\begin{bmatrix} + 1 & 2 & 3\\\\ + 2 & 4 & 5\\\\ + 3 & 5 & 6 +\\end{bmatrix} +``` +and to ``(1, 2\\sqrt{2}, 3\\sqrt{2}, 4, 5\\sqrt{2}, 6)`` for `PositiveSemidefiniteConeScaled`. +""" +struct PositiveSemidefiniteConeScaled <: AbstractSet + dim::Int +end + +dimension(s::Union{PositiveSemidefiniteConeScaled, PositiveSemidefiniteConeTriangle}) = (s.dim * (s.dim + 1)) / 2 """ Integers(n) From 5a7e00ff481f9e7be7355e0ce589a464efefff08 Mon Sep 17 00:00:00 2001 From: Chris Coey Date: Mon, 26 Jun 2017 18:15:17 -0400 Subject: [PATCH 74/83] added exp and pow sets, tidied definitions --- src/SolverInterface/sets.jl | 122 ++++++++++++++++++++++-------------- 1 file changed, 74 insertions(+), 48 deletions(-) diff --git a/src/SolverInterface/sets.jl b/src/SolverInterface/sets.jl index a570e18..2e766f0 100644 --- a/src/SolverInterface/sets.jl +++ b/src/SolverInterface/sets.jl @@ -5,41 +5,50 @@ Abstract supertype for set objects used to encode constraints. """ abstract type AbstractSet end +dimension(s::AbstractSet) = s.dim """ - NonNegative(n) + Free(dim) -The nonnegative orthant ``\\{ x \\in \\mathbb{R}^n : x \\ge 0 \\}`` where the dimension ``n`` is specified by the field `n`. +The set ``\\mathbb{R}^{dim}`` (containing all points) of dimension ``dim``. """ -struct NonNegative <: AbstractSet +struct Zero <: AbstractSet dim::Int end """ - NonPositive(n) + Zero(dim) -The nonpositive orthant ``\\{ x \\in \\mathbb{R}^n : x \\le 0 \\}`` where the dimension ``n`` is specified by the field `n`. +The set ``\\{ 0 \\}^{dim}`` (containing only the origin) of dimension ``dim``. """ -struct NonPositive <: AbstractSet +struct Zero <: AbstractSet dim::Int end """ - Zero(n) + NonNegative(dim) -The set ``\\{0\\}^n`` where the dimension ``n`` is specified by the field `n`. +The nonnegative orthant ``\\{ x \\in \\mathbb{R}^{dim} : x \\ge 0 \\}`` of dimension ``dim``. """ -struct Zero <: AbstractSet +struct NonNegative <: AbstractSet dim::Int end +""" + NonPositive(dim) + +The nonpositive orthant ``\\{ x \\in \\mathbb{R}^{dim} : x \\le 0 \\}`` of dimension ``dim``. +""" +struct NonPositive <: AbstractSet + dim::Int +end """ Interval(lower,upper) -The set ``[l,u] \\subseteq \\mathbb{R}^n`` where ``l`` and ``u`` are specified by `lower` and `upper`, respectively. We allow `lower` and `upper` to be `-Inf` or `Inf`, in which case the set is interpreted as a one-sided interval. +The box ``[lower, upper] \\subseteq \\mathbb{R}^{dim}`` where ``lower`` and ``upper`` are vectors of dimension ``dim``. If ``lower`` or ``upper`` is all ``-Inf`` or ``Inf``, the set is interpreted as a one-sided interval. """ -struct Interval{T} <: AbstractSet +struct Interval{T <: Real} <: AbstractSet lower::T upper::T end @@ -47,27 +56,54 @@ end dimension(s::Interval) = length(s.lower) """ - SecondOrderCone(n) + SecondOrderCone(dim) -The second-order cone or the Lorenz cone of dimension `n` -defined as -```math -\\{ (t,x) \\in \\mathbb{R}^n : t \\ge ||x||_2 \\}. -``` +The second-order cone (or Lorenz cone) ``\\{ (t,x) \\in \\mathbb{R}^{dim} : t \\ge || x ||_2 \\}`` of dimension ``dim``. """ struct SecondOrderCone <: AbstractSet dim::Int end -#ExponentialCone +""" + ExponentialCone() + +The 3-dimensional exponential cone ``\\{ (x,y,z) \\in \\mathbb{R}^3 : y \\exp{x/y} \\le z, y > 0 \\}``. +""" +struct ExponentialCone <: AbstractSet +end + +""" + DualExponentialCone() + +The 3-dimensional dual exponential cone ``\\{ (u,v,w) \\in \\mathbb{R}^3 : -u \\exp{v/u} \\le \\exp{1} w, u < 0 \\}``. +""" +struct DualExponentialCone <: AbstractSet +end + +""" + PowerCone(a) + +The 3-dimensional power cone ``\\{ (x,y,z) \\in \\mathbb{R}^3 : x^{a} y^{1-a} >= |z|, x \\ge 0, y \\ge 0 \\}`` with parameter ``a``. +""" +struct PowerCone{T <: Real} <: AbstractSet + a::T +end + +""" + DualPowerCone(a) + +The 3-dimensional power cone ``\\{ (u,v,w) \\in \\mathbb{R}^3 : (u/a)^a (v/(1-a))^{1-a} >= |w|, u \\ge 0, v \\ge 0 \\}`` with parameter ``a``. +""" +struct DualPowerCone{T <: Real} <: AbstractSet + a::T +end + +dimension(s::Union{ExponentialCone, DualExponentialCone, PowerCone, DualPowerCone}) = 3 """ - PositiveSemidefiniteConeTriangle(n) + PositiveSemidefiniteConeTriangle(dim) -The cone of symmetric ``n \\times n`` matrices that are positive semidefinite. -The dimension of the cone is ``n(n+1)/2`` since the matrices are symmetric. -The entries of the upper triangular part of the matrix are given row by row (or equivalently, the entries of the lower triangular part are given column by column). -The scalar product is the sum of the pairwise product of the diagonal entries plus twice the sum of the pairwise product of the upper diagonal entries. +The cone of symmetric ``dim \\times dim`` matrices that are positive semidefinite. The dimension of the cone is ``dim (dim + 1)/2`` since the matrices are symmetric. The entries of the upper triangular part of the matrix are given row by row (or equivalently, the entries of the lower triangular part are given column by column). The scalar product is the sum of the pairwise product of the diagonal entries plus twice the sum of the pairwise product of the upper diagonal entries. ### Examples @@ -83,15 +119,13 @@ corresponds to ``(1, 2, 3, 4, 5, 6)`` for `PositiveSemidefiniteConeTriangle` """ struct PositiveSemidefiniteConeTriangle <: AbstractSet dim::Int + sidedim::Int end """ PositiveSemidefiniteConeScaled(n) -The cone of symmetric ``n \\times n`` matrices that are positive semidefinite. -The dimension of the cone is ``n(n+1)/2`` since the matrices are symmetric. -The entries of the upper triangular part of the matrix are given row by row (or equivalently, the entries of the lower triangular part are given column by column). -The off-diagonal entries of the matrices of both the cone and its dual are scaled by ``\\sqrt{2}`` and the scalar product is simply the sum of the pairwise product of the entries. +The cone of symmetric ``dim \\times dim`` matrices that are positive semidefinite. The dimension of the cone is ``dim (dim + 1)/2`` since the matrices are symmetric. The entries of the upper triangular part of the matrix are given row by row (or equivalently, the entries of the lower triangular part are given column by column). The off-diagonal entries of the matrices of both the cone and its dual are scaled by ``\\sqrt{2}`` and the scalar product is simply the sum of the pairwise product of the entries. ### Examples @@ -107,51 +141,43 @@ and to ``(1, 2\\sqrt{2}, 3\\sqrt{2}, 4, 5\\sqrt{2}, 6)`` for `PositiveSemidefini """ struct PositiveSemidefiniteConeScaled <: AbstractSet dim::Int + sidedim::Int end -dimension(s::Union{PositiveSemidefiniteConeScaled, PositiveSemidefiniteConeTriangle}) = (s.dim * (s.dim + 1)) / 2 - """ - Integers(n) + Integers(dim) -The set of integers ``\\mathbb{Z}^n``. +The set of integers ``\\mathbb{Z}^{dim}``. """ struct Integers <: AbstractSet dim::Int end """ - Binaries(n) + Binaries(dim) -The set of binary vectors ``\\{0,1\\}^n``. +The set of binary vectors ``\\{ 0, 1 \\}^{dim}``. """ struct Binaries <: AbstractSet dim::Int end - -dimension(s::Union{NonNegative,NonPositive,Zero,SecondOrderCone,Integers,Binaries}) = s.dim - """ - SOS1(weights::Vector{T}) where T - -The set corresponding to the special ordered set (SOS) constraint of type 1. Of the variables in the set, at most one can be nonzero. The ``weights`` induce an ordering of the variables; as such, they should be unique values. The ``k``-th element in the set corresponds to the ``k``-th weight in ``weights``. + SOS1(weights) -See [here](http://lpsolve.sourceforge.net/5.5/SOS.htm) for a description of SOS constraints and their potential uses. +The set corresponding to the special ordered set (SOS) constraint of type 1. Of the variables in the set, at most one can be nonzero. The ``weights`` induce an ordering of the variables; as such, they should be unique values. The ``k``-th element in the set corresponds to the ``k``-th weight in ``weights``. See [here](http://lpsolve.sourceforge.net/5.5/SOS.htm) for a description of SOS constraints and their potential uses. """ -struct SOS1{T} <: AbstractSet +struct SOS1{T <: Real} <: AbstractSet weights::Vector{T} end -dimension(s::SOS1) = length(s.weights) """ - SOS2(weights::Vector{T}) where T + SOS2(weights) -The set corresponding to the special ordered set (SOS) constraint of type 2. Of the variables in the set, at most two can be nonzero, and if two are nonzero, they must be adjacent in the ordering of the set. The ``weights`` induce an ordering of the variables; as such, they should be unique values. The ``k``-th element in the set corresponds to the ``k``-th weight in ``weights``. - -See [here](http://lpsolve.sourceforge.net/5.5/SOS.htm) for a description of SOS constraints and their potential uses. +The set corresponding to the special ordered set (SOS) constraint of type 2. Of the variables in the set, at most two can be nonzero, and if two are nonzero, they must be adjacent in the ordering of the set. The ``weights`` induce an ordering of the variables; as such, they should be unique values. The ``k``-th element in the set corresponds to the ``k``-th weight in ``weights``. See [here](http://lpsolve.sourceforge.net/5.5/SOS.htm) for a description of SOS constraints and their potential uses. """ -struct SOS2{T} <: AbstractSet +struct SOS2{T <: Real} <: AbstractSet weights::Vector{T} end -dimension(s::SOS2) = length(s.weights) + +dimension(s::Union{SOS1, SOS2}) = length(s.weights) From 92e3da9588d57c21a24c5f8cb9a50db37a335e05 Mon Sep 17 00:00:00 2001 From: Chris C Date: Mon, 26 Jun 2017 21:58:31 -0400 Subject: [PATCH 75/83] address comments change free to reals, sidedim to matrix_dim, type of interval --- src/SolverInterface/sets.jl | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/SolverInterface/sets.jl b/src/SolverInterface/sets.jl index 2e766f0..d2d25c0 100644 --- a/src/SolverInterface/sets.jl +++ b/src/SolverInterface/sets.jl @@ -8,11 +8,11 @@ abstract type AbstractSet end dimension(s::AbstractSet) = s.dim """ - Free(dim) + Reals(dim) The set ``\\mathbb{R}^{dim}`` (containing all points) of dimension ``dim``. """ -struct Zero <: AbstractSet +struct Free <: AbstractSet dim::Int end @@ -46,9 +46,9 @@ end """ Interval(lower,upper) -The box ``[lower, upper] \\subseteq \\mathbb{R}^{dim}`` where ``lower`` and ``upper`` are vectors of dimension ``dim``. If ``lower`` or ``upper`` is all ``-Inf`` or ``Inf``, the set is interpreted as a one-sided interval. +The box ``[lower, upper] \\subseteq \\mathbb{R}^{dim}`` where ``lower`` and ``upper`` are scalars (1-dimensional) or vectors of dimension ``dim``. If ``lower`` or ``upper`` is all ``-Inf`` or ``Inf``, the set is interpreted as a one-sided interval. """ -struct Interval{T <: Real} <: AbstractSet +struct Interval{T} <: AbstractSet lower::T upper::T end @@ -119,7 +119,7 @@ corresponds to ``(1, 2, 3, 4, 5, 6)`` for `PositiveSemidefiniteConeTriangle` """ struct PositiveSemidefiniteConeTriangle <: AbstractSet dim::Int - sidedim::Int + matrix_dim::Int end """ @@ -141,7 +141,7 @@ and to ``(1, 2\\sqrt{2}, 3\\sqrt{2}, 4, 5\\sqrt{2}, 6)`` for `PositiveSemidefini """ struct PositiveSemidefiniteConeScaled <: AbstractSet dim::Int - sidedim::Int + matrix_dim::Int end """ From a58ab57fb83fef2b535ef0db307d3b9adb5a6f1f Mon Sep 17 00:00:00 2001 From: Chris C Date: Mon, 26 Jun 2017 22:25:22 -0400 Subject: [PATCH 76/83] tidy PSD definitions --- src/SolverInterface/sets.jl | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/SolverInterface/sets.jl b/src/SolverInterface/sets.jl index d2d25c0..b7a69ec 100644 --- a/src/SolverInterface/sets.jl +++ b/src/SolverInterface/sets.jl @@ -103,7 +103,10 @@ dimension(s::Union{ExponentialCone, DualExponentialCone, PowerCone, DualPowerCon """ PositiveSemidefiniteConeTriangle(dim) -The cone of symmetric ``dim \\times dim`` matrices that are positive semidefinite. The dimension of the cone is ``dim (dim + 1)/2`` since the matrices are symmetric. The entries of the upper triangular part of the matrix are given row by row (or equivalently, the entries of the lower triangular part are given column by column). The scalar product is the sum of the pairwise product of the diagonal entries plus twice the sum of the pairwise product of the upper diagonal entries. +The (vectorized) cone of symmetric positive semidefinite matrices, with off-diagonals unscaled. +The entries of the upper triangular part of the matrix are given row by row (or equivalently, the entries of the lower triangular part are given column by column). +An ``n \\times n`` matrix has ``n(n+1)/2`` lower-triangular elements, so for the vectorized cone of dimension ``dim``, the corresponding symmetric matrix has side dimension ``\\sqrt (1/4 + 2 dim) - 1/2`` elements. +The scalar product is the sum of the pairwise product of the diagonal entries plus twice the sum of the pairwise product of the upper diagonal entries. ### Examples @@ -119,13 +122,15 @@ corresponds to ``(1, 2, 3, 4, 5, 6)`` for `PositiveSemidefiniteConeTriangle` """ struct PositiveSemidefiniteConeTriangle <: AbstractSet dim::Int - matrix_dim::Int end """ - PositiveSemidefiniteConeScaled(n) + PositiveSemidefiniteConeScaled(dim) -The cone of symmetric ``dim \\times dim`` matrices that are positive semidefinite. The dimension of the cone is ``dim (dim + 1)/2`` since the matrices are symmetric. The entries of the upper triangular part of the matrix are given row by row (or equivalently, the entries of the lower triangular part are given column by column). The off-diagonal entries of the matrices of both the cone and its dual are scaled by ``\\sqrt{2}`` and the scalar product is simply the sum of the pairwise product of the entries. +The (vectorized) cone of symmetric positive semidefinite matrices, with off-diagonals scaled. +The entries of the upper triangular part of the matrix are given row by row (or equivalently, the entries of the lower triangular part are given column by column). +An ``n \\times n`` matrix has ``n(n+1)/2`` lower-triangular elements, so for the vectorized cone of dimension ``dim``, the corresponding symmetric matrix has side dimension ``\\sqrt (1/4 + 2 dim) - 1/2`` elements. +The off-diagonal entries of the matrices of both the cone and its dual are scaled by ``\\sqrt{2}`` and the scalar product is simply the sum of the pairwise product of the entries. ### Examples @@ -141,7 +146,6 @@ and to ``(1, 2\\sqrt{2}, 3\\sqrt{2}, 4, 5\\sqrt{2}, 6)`` for `PositiveSemidefini """ struct PositiveSemidefiniteConeScaled <: AbstractSet dim::Int - matrix_dim::Int end """ From 73d3303f9768cef40fe88da51f82aef73c9a9a26 Mon Sep 17 00:00:00 2001 From: Miles Lubin Date: Tue, 27 Jun 2017 14:42:00 -0400 Subject: [PATCH 77/83] empty manual --- docs/make.jl | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/make.jl b/docs/make.jl index b35eaa7..2b789de 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -5,6 +5,7 @@ makedocs( sitename = "MathProgBase", pages = [ "Introduction" => "index.md", + "Solver Interface Manual" => "apimanual.md", "Solver Interface API" => "apireference.md", "High-level Interfaces" => "highlevel.md", "Choosing Solvers" => "choosingsolver.md" From 9980f875c29b6ebd6c72f845108d78f1e7ae4b30 Mon Sep 17 00:00:00 2001 From: Miles Lubin Date: Tue, 27 Jun 2017 14:47:17 -0400 Subject: [PATCH 78/83] missing file --- docs/src/apimanual.md | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 docs/src/apimanual.md diff --git a/docs/src/apimanual.md b/docs/src/apimanual.md new file mode 100644 index 0000000..5cc18f0 --- /dev/null +++ b/docs/src/apimanual.md @@ -0,0 +1,6 @@ + +# Solver Interface Manual + +## Concepts + + From 564d6457705c9e5da98426e4c24266712de5f515 Mon Sep 17 00:00:00 2001 From: Chris Coey Date: Tue, 27 Jun 2017 16:09:21 -0400 Subject: [PATCH 79/83] potential math definition of set problem --- docs/src/apimanual.md | 10 +++++++- docs/src/apireference.md | 50 +++++++++++++++++++------------------ src/SolverInterface/sets.jl | 16 ++++++------ 3 files changed, 43 insertions(+), 33 deletions(-) diff --git a/docs/src/apimanual.md b/docs/src/apimanual.md index 5cc18f0..ae37a41 100644 --- a/docs/src/apimanual.md +++ b/docs/src/apimanual.md @@ -3,4 +3,12 @@ ## Concepts - +```math +\begin{align} + & \min_{x \in \mathbb{R}^n} & f_0(x) + \\ + & \;\;\text{s.t.} & f_i(x) & \in \mathcal{S}_i & i = 1 \ldots m + \\ + & & x & \in [l, u] +\end{align} +``` diff --git a/docs/src/apireference.md b/docs/src/apireference.md index d10e2ee..29017fc 100644 --- a/docs/src/apireference.md +++ b/docs/src/apireference.md @@ -12,7 +12,6 @@ AbstractNLPModel AbstractMathProgSolver ``` - ```@docs Model NLPModel @@ -22,7 +21,6 @@ freemodel! ## Variables - ```@docs VariableReference candelete(::AbstractMathProgModel,::VariableReference) @@ -63,11 +61,17 @@ getconstraintquadratic List of sets. ```@docs +AbstractSet +Reals +Zero NonNegative NonPositive -Zero Interval SecondOrderCone +ExponentialCone +DualExponentialCone +PowerCone +DualPowerCone PositiveSemidefiniteConeTriangle PositiveSemidefiniteConeScaled Integers @@ -76,25 +80,16 @@ SOS1 SOS2 ``` -## Attributes - -These are used to get and set properties of the model or solver. - +Functions for getting and setting properties of sets. ```@docs -AbstractSolverOrModelAttribute -AbstractVariableAttribute -AbstractConstraintAttribute -cangetattribute -getattribute -getattribute! -cansetattribute -setattribute! +dimension ``` -### Solver or Model Attributes +## Attributes -These attribute apply to solver or model objects, as noted. +### Solver or Model Attributes +List of solver or model attributes. ```@docs ReturnsDuals SupportsAddConstraintAfterSolve @@ -124,10 +119,21 @@ PrimalStatus DualStatus ``` -### Variable Attributes +Functions for getting and setting model or solver attributes. +```@docs +AbstractSolverOrModelAttribute +AbstractVariableAttribute +AbstractConstraintAttribute +cangetattribute +getattribute +getattribute! +cansetattribute +setattribute! +``` -These attributes are associated with variables. Calls to `getattribute` and `setattribute!` should include as an argument a single `VariableReference` or a vector of `VariableReference` objects. By convention, the name of a variable attributes begins with `Variable`. +### Variable Attributes +List of attributes associated with variables. Calls to `getattribute` and `setattribute!` should include as an argument a single `VariableReference` or a vector of `VariableReference` objects. ```@docs VariablePrimalStart VariableLowerBoundDualStart @@ -142,9 +148,7 @@ VariableBasisStatus ### Constraint Attributes -These attributes are associated with constraints. Calls to `getattribute` and `setattribute!` should include as an argument a single `ConstraintReference` or a vector of `ConstriaintReference{T}` objects. By convention, the name of a variable attributes begins with `Variable`. - - +List of attributes associated with constraints. Calls to `getattribute` and `setattribute!` should include as an argument a single `ConstraintReference` or a vector of `ConstriaintReference{T}` objects. ```@docs ConstraintPrimalStart ConstraintDualStart @@ -158,7 +162,6 @@ ConstraintBasisStatus ### Termination Status The `TerminationStatus` attribute is meant to explain the reason why the solver stopped executing. The value of the attribute is of type `TerminationStatusCode`. - ```@docs TerminationStatusCode ``` @@ -166,7 +169,6 @@ TerminationStatusCode ### Result Status The `PrimalStatus` and `DualStatus` attributes are meant to explain how to interpret the result returned by the solver. The value of the attributes are of type `ResultStatusCode`. - ```@docs ResultStatusCode ``` diff --git a/src/SolverInterface/sets.jl b/src/SolverInterface/sets.jl index b7a69ec..2483efa 100644 --- a/src/SolverInterface/sets.jl +++ b/src/SolverInterface/sets.jl @@ -12,7 +12,7 @@ dimension(s::AbstractSet) = s.dim The set ``\\mathbb{R}^{dim}`` (containing all points) of dimension ``dim``. """ -struct Free <: AbstractSet +struct Reals <: AbstractSet dim::Int end @@ -67,7 +67,7 @@ end """ ExponentialCone() -The 3-dimensional exponential cone ``\\{ (x,y,z) \\in \\mathbb{R}^3 : y \\exp{x/y} \\le z, y > 0 \\}``. +The 3-dimensional exponential cone ``\\{ (x,y,z) \\in \\mathbb{R}^3 : y \\exp (x/y) \\le z, y > 0 \\}``. """ struct ExponentialCone <: AbstractSet end @@ -75,7 +75,7 @@ end """ DualExponentialCone() -The 3-dimensional dual exponential cone ``\\{ (u,v,w) \\in \\mathbb{R}^3 : -u \\exp{v/u} \\le \\exp{1} w, u < 0 \\}``. +The 3-dimensional dual exponential cone ``\\{ (u,v,w) \\in \\mathbb{R}^3 : -u \\exp (v/u) \\le \\exp(1) w, u < 0 \\}``. """ struct DualExponentialCone <: AbstractSet end @@ -104,8 +104,8 @@ dimension(s::Union{ExponentialCone, DualExponentialCone, PowerCone, DualPowerCon PositiveSemidefiniteConeTriangle(dim) The (vectorized) cone of symmetric positive semidefinite matrices, with off-diagonals unscaled. -The entries of the upper triangular part of the matrix are given row by row (or equivalently, the entries of the lower triangular part are given column by column). -An ``n \\times n`` matrix has ``n(n+1)/2`` lower-triangular elements, so for the vectorized cone of dimension ``dim``, the corresponding symmetric matrix has side dimension ``\\sqrt (1/4 + 2 dim) - 1/2`` elements. +The entries of the upper triangular part of the matrix are given row by row (or equivalently, the entries of the lower triangular part are given column by column). +An ``n \\times n`` matrix has ``n(n+1)/2`` lower-triangular elements, so for the vectorized cone of dimension ``dim``, the corresponding symmetric matrix has side dimension ``\\sqrt (1/4 + 2 dim) - 1/2`` elements. The scalar product is the sum of the pairwise product of the diagonal entries plus twice the sum of the pairwise product of the upper diagonal entries. ### Examples @@ -128,9 +128,9 @@ end PositiveSemidefiniteConeScaled(dim) The (vectorized) cone of symmetric positive semidefinite matrices, with off-diagonals scaled. -The entries of the upper triangular part of the matrix are given row by row (or equivalently, the entries of the lower triangular part are given column by column). -An ``n \\times n`` matrix has ``n(n+1)/2`` lower-triangular elements, so for the vectorized cone of dimension ``dim``, the corresponding symmetric matrix has side dimension ``\\sqrt (1/4 + 2 dim) - 1/2`` elements. -The off-diagonal entries of the matrices of both the cone and its dual are scaled by ``\\sqrt{2}`` and the scalar product is simply the sum of the pairwise product of the entries. +The entries of the upper triangular part of the matrix are given row by row (or equivalently, the entries of the lower triangular part are given column by column). +An ``n \\times n`` matrix has ``n(n+1)/2`` lower-triangular elements, so for the vectorized cone of dimension ``dim``, the corresponding symmetric matrix has side dimension ``\\sqrt (1/4 + 2 dim) - 1/2`` elements. +The off-diagonal entries of the matrices of both the cone and its dual are scaled by ``\\sqrt{2}`` and the scalar product is simply the sum of the pairwise product of the entries. ### Examples From b9b8e54c6425ae47ffaa55a398fe49f058573bdf Mon Sep 17 00:00:00 2001 From: Miles Lubin Date: Wed, 28 Jun 2017 15:00:16 -0400 Subject: [PATCH 80/83] another pass on sets --- docs/src/apireference.md | 10 ++++--- src/SolverInterface/sets.jl | 55 +++++++++++++++++++++++++------------ 2 files changed, 44 insertions(+), 21 deletions(-) diff --git a/docs/src/apireference.md b/docs/src/apireference.md index 29017fc..f7941b6 100644 --- a/docs/src/apireference.md +++ b/docs/src/apireference.md @@ -63,9 +63,11 @@ List of sets. ```@docs AbstractSet Reals -Zero -NonNegative -NonPositive +Zeros +NonNegatives +NonPositives +GreaterThan +LessThan Interval SecondOrderCone ExponentialCone @@ -75,7 +77,7 @@ DualPowerCone PositiveSemidefiniteConeTriangle PositiveSemidefiniteConeScaled Integers -Binaries +ZeroOne SOS1 SOS2 ``` diff --git a/src/SolverInterface/sets.jl b/src/SolverInterface/sets.jl index 2483efa..aa3c695 100644 --- a/src/SolverInterface/sets.jl +++ b/src/SolverInterface/sets.jl @@ -5,6 +5,11 @@ Abstract supertype for set objects used to encode constraints. """ abstract type AbstractSet end +""" + dimension(s::AbstractSet) + +Return the dimension (number of vector components) in the set `s`. +""" dimension(s::AbstractSet) = s.dim """ @@ -17,43 +22,61 @@ struct Reals <: AbstractSet end """ - Zero(dim) + Zeros(dim) The set ``\\{ 0 \\}^{dim}`` (containing only the origin) of dimension ``dim``. """ -struct Zero <: AbstractSet +struct Zeros <: AbstractSet dim::Int end """ - NonNegative(dim) + NonNegatives(dim) The nonnegative orthant ``\\{ x \\in \\mathbb{R}^{dim} : x \\ge 0 \\}`` of dimension ``dim``. """ -struct NonNegative <: AbstractSet +struct NonNegatives <: AbstractSet dim::Int end """ - NonPositive(dim) + NonPositives(dim) The nonpositive orthant ``\\{ x \\in \\mathbb{R}^{dim} : x \\le 0 \\}`` of dimension ``dim``. """ -struct NonPositive <: AbstractSet +struct NonPositives <: AbstractSet dim::Int end +""" + GreaterThan(lower) + +The set ``[lower,\\infty] \\subseteq \\mathbb{R}``. +""" +struct GreaterThan{T <: Real} <: AbstractSet + lower::T +end + +""" + LessThan(upper) + +The set ``(-\\infty,upper] \\subseteq \\mathbb{R}``. +""" +struct LessThan{T <: Real} <: AbstractSet + upper::T +end + """ Interval(lower,upper) -The box ``[lower, upper] \\subseteq \\mathbb{R}^{dim}`` where ``lower`` and ``upper`` are scalars (1-dimensional) or vectors of dimension ``dim``. If ``lower`` or ``upper`` is all ``-Inf`` or ``Inf``, the set is interpreted as a one-sided interval. +The interval ``[lower, upper] \\subseteq \\mathbb{R}``. If ``lower`` or ``upper`` is ``-Inf`` or ``Inf``, respectively, the set is interpreted as a one-sided interval. """ -struct Interval{T} <: AbstractSet +struct Interval{T <: Real} <: AbstractSet lower::T upper::T end -dimension(s::Interval) = length(s.lower) +dimension(s::Union{Interval,GreaterThan,LessThan}) = 1 """ SecondOrderCone(dim) @@ -149,20 +172,18 @@ struct PositiveSemidefiniteConeScaled <: AbstractSet end """ - Integers(dim) + Integers() -The set of integers ``\\mathbb{Z}^{dim}``. +The set of integers ``\\mathbb{Z}``. """ -struct Integers <: AbstractSet - dim::Int -end +struct Integers <: AbstractSet end """ - Binaries(dim) + ZeroOne() -The set of binary vectors ``\\{ 0, 1 \\}^{dim}``. +The set ``\\{ 0, 1 \\}``. """ -struct Binaries <: AbstractSet +struct ZeroOne <: AbstractSet dim::Int end From 699698f0da7e6626de5c90f5ce291a8b7f8c2cde Mon Sep 17 00:00:00 2001 From: Miles Lubin Date: Wed, 28 Jun 2017 15:27:02 -0400 Subject: [PATCH 81/83] tidy --- src/SolverInterface/sets.jl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/SolverInterface/sets.jl b/src/SolverInterface/sets.jl index aa3c695..1ea3f29 100644 --- a/src/SolverInterface/sets.jl +++ b/src/SolverInterface/sets.jl @@ -51,7 +51,7 @@ end """ GreaterThan(lower) -The set ``[lower,\\infty] \\subseteq \\mathbb{R}``. +The set ``[lower,\\infty) \\subseteq \\mathbb{R}``. """ struct GreaterThan{T <: Real} <: AbstractSet lower::T @@ -183,9 +183,9 @@ struct Integers <: AbstractSet end The set ``\\{ 0, 1 \\}``. """ -struct ZeroOne <: AbstractSet - dim::Int -end +struct ZeroOne <: AbstractSet end + +dimension(s::Union{Integers,ZeroOne}) = 1 """ SOS1(weights) From 81ce4cd25351544e4f15f0a883bb6aa366b05e7e Mon Sep 17 00:00:00 2001 From: Miles Lubin Date: Wed, 28 Jun 2017 20:08:42 -0400 Subject: [PATCH 82/83] remove variable bound attributes and add basic discussion of duals --- docs/src/apimanual.md | 33 ++++++++++++++++++-- docs/src/apireference.md | 10 ------- src/SolverInterface/attributes.jl | 50 ------------------------------- 3 files changed, 31 insertions(+), 62 deletions(-) diff --git a/docs/src/apimanual.md b/docs/src/apimanual.md index ae37a41..95a6708 100644 --- a/docs/src/apimanual.md +++ b/docs/src/apimanual.md @@ -3,12 +3,41 @@ ## Concepts +We define the standard form problem as: + ```math \begin{align} & \min_{x \in \mathbb{R}^n} & f_0(x) \\ & \;\;\text{s.t.} & f_i(x) & \in \mathcal{S}_i & i = 1 \ldots m - \\ - & & x & \in [l, u] \end{align} ``` + +At the moment all functions are described compactly with lists, vectors, and matrices. NLP is a special case discussed later. An objective function ``f_0`` can be affine or quadratic. The constraint functions ``f_i`` can be variablewise, affine, or quadratic (to be defined). + +## Duals + +We take the convention that duals on lower bounds (`GreaterThan`) should be nonnegative, duals on upper bounds (`LessThan`) should be nonpositive, and duals on closed convex cones should belong to the dual cone. + +For minimization problems in conic form, we can define the primal as: + +```math +\begin{align} +& \min_{x \in \mathbb{R}^n} & b_0^Tx +\\ +& \;\;\text{s.t.} & A_ix + b_i & \in \mathcal{C}_i & \forall i +\end{align} +``` +and the dual as: + +```math +\begin{align} +& \max_{y_i \forall i} & -\sum_i b_i^T y_i +\\ +& \;\;\text{s.t.} & b_0 - \sum_i A_i^T y_i &= 0 +\\ +& & y_i \in \mathcal{C}_i^* && \forall i +\end{align} +``` + +``a^Tx + b \ge c`` should be interpreted (for the purposes of duals) as ``a^Tx + b - c \in \mathbb{R}_+``, and similarly ``a^Tx + b \le c`` should be interpreted (for the purposes of duals) as ``a^Tx + b - c \in \mathbb{R}_-``. Variablewise constraints should be interpreted as affine constraints with the appropriate identity mapping in place of ``A_i``. diff --git a/docs/src/apireference.md b/docs/src/apireference.md index f7941b6..9d3f2f5 100644 --- a/docs/src/apireference.md +++ b/docs/src/apireference.md @@ -138,13 +138,7 @@ setattribute! List of attributes associated with variables. Calls to `getattribute` and `setattribute!` should include as an argument a single `VariableReference` or a vector of `VariableReference` objects. ```@docs VariablePrimalStart -VariableLowerBoundDualStart -VariableUpperBoundDualStart -VariableLowerBound -VariableUpperBound VariablePrimal -VariableLowerBoundDual -VariableUpperBoundDual VariableBasisStatus ``` @@ -181,10 +175,6 @@ ResultStatusCode BasisStatusCode ``` -## Duals - -We take the convention that duals on variable lower bounds should be nonnegative, duals on variable upper bounds should be nonpositive, and duals on closed convex cones should belong to the dual cone. - ## Nonlinear Programming (NLP) diff --git a/src/SolverInterface/attributes.jl b/src/SolverInterface/attributes.jl index 86963b3..bc0d860 100644 --- a/src/SolverInterface/attributes.jl +++ b/src/SolverInterface/attributes.jl @@ -356,36 +356,6 @@ to warm-start the solve. """ struct VariablePrimalStart <: AbstractVariableAttribute end -""" - VariableLowerBoundDualStart() - -An initial assignment of the variable lower-bound duals that the solver may use -to warm-start the solve. -""" -struct VariableLowerBoundDualStart <: AbstractVariableAttribute end - -""" - VariableUpperBoundDualStart() - -An initial assignment of the variable upper-bound duals that the solver may use -to warm-start the solve. -""" -struct VariableUpperBoundDualStart <: AbstractVariableAttribute end - -""" - VariableLowerBound() - -Lower-bound constraints on variables. `-Inf` is valid as no bound. -""" -struct VariableLowerBound <: AbstractVariableAttribute end - -""" - VariableUpperBound() - -Upper-bound constraints for the variables. `Inf` is valid as no bound. -""" -struct VariableUpperBound <: AbstractVariableAttribute end - """ VariablePrimal(N) VariablePrimal() @@ -397,26 +367,6 @@ struct VariablePrimal <: AbstractVariableAttribute end VariablePrimal() = VariablePrimal(1) -""" - VariableLowerBoundDual(N) - -The assignment to the duals on the variable lower bounds in result `N`. If `N` is omitted, it is interpreted as 1. -""" -struct VariableLowerBoundDual <: AbstractVariableAttribute - N::Int -end -VariableLowerBoundDual() = VariableLowerBoundDual(1) - -""" - VariableUpperBoundDual(N) - -The assignment to the duals on the variable upper bounds in result `N`. If `N` is omitted, it is interpreted as 1. -""" -struct VariableUpperBoundDual <: AbstractVariableAttribute - N::Int -end -VariableUpperBoundDual() = VariableUpperBoundDual(1) - """ VariableBasisStatus() From d9a1074eda4cb4ab282b6c743d6e0d67531f7148 Mon Sep 17 00:00:00 2001 From: Miles Lubin Date: Thu, 29 Jun 2017 11:55:15 -0400 Subject: [PATCH 83/83] 1-d variablewise constraints --- src/SolverInterface/constraints.jl | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/SolverInterface/constraints.jl b/src/SolverInterface/constraints.jl index 022e609..5aba465 100644 --- a/src/SolverInterface/constraints.jl +++ b/src/SolverInterface/constraints.jl @@ -57,6 +57,15 @@ Add the constraint x_{varref} \\in S ``` where `varref` is a vector of variable references to specifiy the subset of the subvector of `x`. + + addconstraint!(m::AbstractMathProgModel, varref::VariableReference, S::AbstractSet)::VariablewiseConstraintReference{typeof(S)} + +A specialized version of `addconstraint!` for one-dimensional variablewise constraints. +Add the constraint +```math +x_{varref} \\in S +``` +where `varref` is a single variable references to specifiy the index of `x`. """ function addconstraint! end