Skip to content
This repository has been archived by the owner on Feb 9, 2020. It is now read-only.

Commit

Permalink
Merge pull request #53 from JuliaOpt/bl/fixtests
Browse files Browse the repository at this point in the history
Updates to Julia v1.0, fixes and implements ListOfConstraint[Indice]s
  • Loading branch information
blegat authored Oct 13, 2018
2 parents 7b45398 + e8ac969 commit a56e0b1
Show file tree
Hide file tree
Showing 7 changed files with 98 additions and 39 deletions.
3 changes: 2 additions & 1 deletion REQUIRE
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
julia 0.7
MathOptInterface 0.6 0.7
Mosek
Mosek
Compat 1
4 changes: 2 additions & 2 deletions src/LinkedInts.jl
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using Printf #
using Printf #

mutable struct LinkedInts
next :: Vector{Int}
Expand All @@ -18,7 +18,7 @@ LinkedInts(capacity=128) =
Int[],
Int[])

allocatedlist(s::LinkedInts) = find(s.block .> 0)
allocatedlist(s::LinkedInts) = findall(s.block .> 0)
allocated(s::LinkedInts, id :: Int) = id > 0 && id <= length(s.block) && s.block[id] > 0
blocksize(s::LinkedInts, id :: Int) = s.size[id]
Base.length(s::LinkedInts) = length(s.next)
Expand Down
15 changes: 13 additions & 2 deletions src/MathOptInterfaceMosek.jl
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ using Mosek

export MosekOptimizer

using Compat # for findall

include("LinkedInts.jl")

Expand Down Expand Up @@ -241,6 +242,14 @@ mutable struct MosekModel <: MOI.AbstractOptimizer
###########################
trm :: Rescode
solutions :: Vector{MosekSolution}

###########################
"""
Indicating whether the objective sense is MOI.FeasibilitySense. It is
encoded as a MOI.MinSense with a zero objective internally but this allows
MOI.get(::MosekModel, ::ObjectiveSense) to still return the right value
"""
feasibility :: Bool
end

function MosekOptimizer(; kws...)
Expand Down Expand Up @@ -288,8 +297,9 @@ function MosekOptimizer(; kws...)
Int[], # c_block_slack
Int[], # c_coneid
0, # cone counter
Mosek.MSK_RES_OK,
MosekSolution[]) # trm
Mosek.MSK_RES_OK,# trm
MosekSolution[],
true) # feasibility_sense
catch
Mosek.deletetask(t)
rethrow()
Expand Down Expand Up @@ -374,6 +384,7 @@ function MOI.empty!(m::MosekModel)
m.conecounter = 0
m.trm = Mosek.MSK_RES_OK
m.solutions = MosekSolution[]
m.feasibility = true
end

function MOI.copy_to(dest::MosekModel, src::MOI.ModelLike; copy_names=true)
Expand Down
64 changes: 52 additions & 12 deletions src/attributes.jl
Original file line number Diff line number Diff line change
Expand Up @@ -18,24 +18,35 @@ MOI.get(m::MosekModel,attr::MOI.SolveTime) = getdouinf(m.task,MSK_DINF_OPTIMIZER


# NOTE: The MOSEK interface currently only supports Min and Max
function MOI.get(m::MosekModel,attr::MOI.ObjectiveSense)
sense = getobjsense(m.task)
if sense == MSK_OBJECTIVE_SENSE_MINIMIZE
MOI.MinSense
function MOI.get(model::MosekModel, ::MOI.ObjectiveSense)
if model.feasibility
return MOI.FeasibilitySense
else
MOI.MaxSense
sense = getobjsense(model.task)
if sense == MSK_OBJECTIVE_SENSE_MINIMIZE
MOI.MinSense
else
MOI.MaxSense
end
end
end

function MOI.set(m::MosekModel,attr::MOI.ObjectiveSense, sense::MOI.OptimizationSense)
function MOI.set(model::MosekModel,
attr::MOI.ObjectiveSense,
sense::MOI.OptimizationSense)
if sense == MOI.MinSense
putobjsense(m.task,MSK_OBJECTIVE_SENSE_MINIMIZE)
model.feasibility = false
putobjsense(model.task,MSK_OBJECTIVE_SENSE_MINIMIZE)
elseif sense == MOI.MaxSense
putobjsense(m.task,MSK_OBJECTIVE_SENSE_MAXIMIZE)
model.feasibility = false
putobjsense(model.task,MSK_OBJECTIVE_SENSE_MAXIMIZE)
else
@assert sense == MOI.FeasibilitySense
putobjsense(m.task,MSK_OBJECTIVE_SENSE_MINIMIZE)
MOI.set(m, MOI.ObjectiveFunction{MOI.ScalarAffineFunction{Float64}}(), MOI.ScalarAffineFunction(MOI.VariableIndex[], Float64[], 0.))
model.feasibility = true
putobjsense(model.task,MSK_OBJECTIVE_SENSE_MINIMIZE)
MOI.set(model,
MOI.ObjectiveFunction{MOI.ScalarAffineFunction{Float64}}(),
MOI.ScalarAffineFunction(MOI.ScalarAffineTerm{Float64}[], 0.0))
end
end

Expand Down Expand Up @@ -71,10 +82,39 @@ MOI.get(m::MosekModel,attr::MOI.ResultCount) = length(m.solutions)

MOI.get(m::MosekModel,attr::MOI.NumberOfVariables) = m.publicnumvar

MOI.get(m::MosekModel,attr::MOI.NumberOfConstraints{F,D}) where {F,D} = length(select(m.constrmap,F,D))
function MOI.get(m::MosekModel, ::MOI.NumberOfConstraints{F,D}) where {F,D}
return length(select(m.constrmap, F, D))
end

#MOI.get{F,D}(m::MosekSolver,attr::MOI.ListOfConstraintIndices{F,D}) = keys(select(m.constrmap,F,D))
function MOI.get(model::MosekModel,
::MOI.ListOfConstraints)
list = Tuple{DataType, DataType}[]
for F in [MOI.SingleVariable, MOI.ScalarAffineFunction{Float64}]
for D in [MOI.LessThan{Float64}, MOI.GreaterThan{Float64},
MOI.EqualTo{Float64}, MOI.Interval{Float64}]
if !isempty(select(model.constrmap, F, D))
push!(list, (F, D))
end
end
end
for F in [MOI.VectorOfVariables, MOI.VectorAffineFunction{Float64}]
for D in [MOI.Nonpositives, MOI.Nonnegatives, MOI.Reals, MOI.Zeros,
MOI.SecondOrderCone, MOI.RotatedSecondOrderCone,
MOI.PowerCone{Float64}, MOI.DualPowerCone{Float64},
MOI.ExponentialCone, MOI.DualExponentialCone,
MOI.PositiveSemidefiniteConeTriangle]
if !isempty(select(model.constrmap, F, D))
push!(list, (F, D))
end
end
end
return list
end

function MOI.get(model::MosekModel,
::MOI.ListOfConstraintIndices{F, D}) where {F, D}
return MOI.ConstraintIndex{F, D}.(keys(select(model.constrmap, F, D)))
end

#### Warm start values

Expand Down
28 changes: 17 additions & 11 deletions src/constraint.jl
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ function MOI.add_constraint(

N = 1
conid = allocateconstraints(m,N)
addlhsblock!(m, conid, fill(1,length(axb.terms)),axb.terms)
addlhsblock!(m, conid, fill(1, length(axb.terms)), axb.terms)

if length(m.c_constant) < length(m.c_block)
append!(m.c_constant,zeros(Float64,length(m.c_block) - length(m.c_constant)))
Expand Down Expand Up @@ -436,7 +436,7 @@ addbound!(m :: MosekModel, conid :: Int, conidxs :: Vector{Int}, constant :: Vec
function addbound!(m :: MosekModel, conid :: Int, conidxs :: Vector{Int}, constant :: Vector{Float64}, dom :: D) where { D <: Union{MOI.ExponentialCone, MOI.DualExponentialCone} }
N = MOI.dimension(dom)
nalloc = ensurefree(m.x_block,N)

varid = newblock(m.x_block,N)
numvar = getnumvar(m.task)
if nalloc > 0
Expand Down Expand Up @@ -651,15 +651,16 @@ end

function MOI.transform(m::MosekModel,
cref::MOI.ConstraintIndex{F,D},
newdom::D) where {F <: MOI.AbstractFunction, D <: MOI.AbstractSet}
newdom::D) where {F <: MOI.AbstractFunction,
D <: MOI.AbstractSet}
MOI.modify(m,cref,newdom)
cref
end

function MOI.transform(m::MosekModel,
cref::MOI.ConstraintIndex{MOI.ScalarAffineFunction{Float64},D1},
newdom::D2) where {D1 <: ScalarLinearDomain,
D2 <: ScalarLinearDomain}
D2 <: ScalarLinearDomain}
F = MOI.ScalarAffineFunction{Float64}

cid = ref2id(cref)
Expand All @@ -670,7 +671,7 @@ function MOI.transform(m::MosekModel,

newcref = MOI.ConstraintIndex{F,D2}(UInt64(cid) << 1)
delete!(select(m.constrmap,F,D1), cref.value)
select(m.constrmap,F, D2)[newcref.value] = cid
select(m.constrmap, F, D2)[newcref.value] = cid
newcref
end

Expand Down Expand Up @@ -850,11 +851,11 @@ function MOI.delete(
# should not happen
end

m.x_numxc[subj] -= 1
m.xc_idxs[sub] = 0
m.x_numxc[subj] .-= 1
m.xc_idxs[sub] .= 0
m.xc_bounds[xcid] = 0

deleteblock(m.xc_block,xcid)
deleteblock(m.xc_block, xcid)
end


Expand Down Expand Up @@ -906,16 +907,21 @@ function allocatevariable(m :: MosekModel,N :: Int)
@assert(length(m.x_boundflags) == length(m.x_block))
numvar = getnumvar(m.task)
alloced = ensurefree(m.x_block,N)
if alloced > 0
if alloced > 0
appendvars(m.task, length(m.x_block) - numvar)
append!(m.x_boundflags, zeros(Int,length(m.x_block) - numvar))
append!(m.x_numxc, zeros(Int,length(m.x_block) - numvar))
end
newblock(m.x_block,N)
end

MOI.isvalid(m::MosekModel, ref::MOI.ConstraintIndex{F,D}) where { F,D } = haskey(select(m.constrmap,F,D),ref.value)
MOI.isvalid(m::MosekModel, ref::MOI.VariableIndex) = allocated(m.x_block,ref2id(ref))
function MOI.is_valid(model::MosekModel,
ref::MOI.ConstraintIndex{F, D}) where {F, D}
return haskey(select(model.constrmap, F, D), ref.value)
end
function MOI.is_valid(model::MosekModel, ref::MOI.VariableIndex)
return allocated(model.x_block, ref2id(ref))
end


function getvarboundlist(t::Mosek.Task, subj :: Vector{Int32})
Expand Down
2 changes: 1 addition & 1 deletion src/objective.jl
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ end

MOI.supports(::MosekModel,::MOI.ObjectiveFunction{<:ObjF}) = true
MOI.supports(::MosekModel,::MOI.ObjectiveSense) = true


function MOI.set(m::MosekModel, ::MOI.ObjectiveFunction, func::MOI.SingleVariable)
numvar = getnumvar(m.task)
Expand Down
21 changes: 11 additions & 10 deletions test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -43,17 +43,18 @@ MOIU.@model(Model,
(MOI.ScalarAffineFunction,),
(MOI.VectorOfVariables,),
(MOI.VectorAffineFunction,))
@testset "Continuous linear problems" begin
MOIT.copytest(optimizer, Model{Float64}())

@testset "Copy" begin
# Currently does not work because get is missing for ConstraintSet
# and ConstraintFunction, see https://github.com/JuliaOpt/MathOptInterfaceMosek.jl/issues/50
#MOIT.copytest(optimizer, Model{Float64}())
end

@testset "Continuous linear problems" begin
# linear1 is failing because NumberOfConstraints does not take deletion into account
# linear11 is failing because the following are not implemented:
# * MOI.cantransformconstraint(instance, c2, MOI.LessThan(2.0))
# * MOI.get(instance, MathOptInterface.ConstraintFunction())
# linear13 is failing because it is FeasibilitySense
MOIT.contlineartest(optimizer, config, ["linear1", "linear11", "linear13"])
# linear1 is failing for two reasons
# * it does not remove constraints using a variable if this variable is deleted, see https://github.com/JuliaOpt/MathOptInterface.jl/issues/511
# * it does not support duplicated terms, see https://github.com/JuliaOpt/MathOptInterfaceMosek.jl/issues/41
MOIT.contlineartest(optimizer, config, ["linear1"])
end

# include("contquadratic.jl")
Expand All @@ -62,8 +63,8 @@ end
# end

@testset "Continuous conic problems" begin
# lin1 and soc1 are failing because ListOfConstraints is not implemented
MOIT.contconictest(MOIB.RootDet{Float64}(MOIB.GeoMean{Float64}(optimizer)), config, ["lin1v", "lin1f", "soc1v", "soc1f", "exp", "psds", "rootdets", "logdet"])
MOIT.contconictest(MOIB.SquarePSD{Float64}(MOIB.RootDet{Float64}(MOIB.GeoMean{Float64}(optimizer))),
config, ["exp", "rootdets", "logdet"])
end

@testset "Mixed-integer linear problems" begin
Expand Down

0 comments on commit a56e0b1

Please sign in to comment.