Skip to content

Commit

Permalink
Merge 054f6a6 into b160ed6
Browse files Browse the repository at this point in the history
  • Loading branch information
mlubin committed Jul 28, 2018
2 parents b160ed6 + 054f6a6 commit f656a57
Show file tree
Hide file tree
Showing 7 changed files with 77 additions and 88 deletions.
23 changes: 12 additions & 11 deletions src/affexpr.jl
Original file line number Diff line number Diff line change
Expand Up @@ -303,8 +303,6 @@ function Base.copy(a::GenericAffExpr, new_model::Model)
return result
end

# TODO GenericAffExprConstraint

struct AffExprConstraint{V <: AbstractVariableRef, S <: MOI.AbstractScalarSet} <: AbstractConstraint
func::GenericAffExpr{Float64, V}
set::S
Expand All @@ -323,15 +321,18 @@ end

moi_function_and_set(c::VectorAffExprConstraint) = (MOI.VectorAffineFunction(c.func), c.set)

function constraintobject(cr::ConstraintRef{Model}, ::Type{AffExpr}, ::Type{SetType}) where {SetType <: MOI.AbstractScalarSet}
f = MOI.get(cr.m, MOI.ConstraintFunction(), cr)::MOI.ScalarAffineFunction
s = MOI.get(cr.m, MOI.ConstraintSet(), cr)::SetType
return AffExprConstraint(AffExpr(cr.m, f), s)
function constraintobject(ref::ConstraintRef{Model, MOICON{FuncType, SetType}}) where
{FuncType <: MOI.ScalarAffineFunction, SetType <: MOI.AbstractScalarSet}
model = ref.m
f = MOI.get(model, MOI.ConstraintFunction(), ref)::FuncType
s = MOI.get(model, MOI.ConstraintSet(), ref)::SetType
return AffExprConstraint(AffExpr(model, f), s)
end

function constraintobject(cr::ConstraintRef{Model}, ::Type{Vector{AffExpr}}, ::Type{SetType}) where {SetType <: MOI.AbstractVectorSet}
m = cr.m
f = MOI.get(m, MOI.ConstraintFunction(), cr)::MOI.VectorAffineFunction
s = MOI.get(m, MOI.ConstraintSet(), cr)::SetType
return VectorAffExprConstraint(map(f -> AffExpr(m, f), MOIU.eachscalar(f)), s)
function constraintobject(ref::ConstraintRef{Model, MOICON{FuncType, SetType}}) where
{FuncType <: MOI.VectorAffineFunction, SetType <: MOI.AbstractVectorSet}
model = ref.m
f = MOI.get(model, MOI.ConstraintFunction(), ref)::MOI.VectorAffineFunction
s = MOI.get(model, MOI.ConstraintSet(), ref)::SetType
return VectorAffExprConstraint(map(f -> AffExpr(model, f), MOIU.eachscalar(f)), s)
end
11 changes: 6 additions & 5 deletions src/quadexpr.jl
Original file line number Diff line number Diff line change
Expand Up @@ -227,11 +227,12 @@ end

moi_function_and_set(c::QuadExprConstraint) = (MOI.ScalarQuadraticFunction(c.func), c.set)

function constraintobject(cr::ConstraintRef{Model}, ::Type{QuadExpr}, ::Type{SetType}) where {SetType <: MOI.AbstractScalarSet}
m = cr.m
f = MOI.get(m.moibackend, MOI.ConstraintFunction(), index(cr))::MOI.ScalarQuadraticFunction
s = MOI.get(m.moibackend, MOI.ConstraintSet(), index(cr))::SetType
return QuadExprConstraint(QuadExpr(m, f), s)
function constraintobject(ref::ConstraintRef{Model, MOICON{FuncType, SetType}}) where
{FuncType <: MOI.ScalarQuadraticFunction, SetType <: MOI.AbstractScalarSet}
model = ref.m
f = MOI.get(model, MOI.ConstraintFunction(), ref)::FuncType
s = MOI.get(model, MOI.ConstraintSet(), ref)::SetType
return QuadExprConstraint(QuadExpr(model, f), s)
end

# TODO: VectorQuadExprConstraint
25 changes: 14 additions & 11 deletions src/variables.jl
Original file line number Diff line number Diff line change
Expand Up @@ -221,17 +221,20 @@ end

moi_function_and_set(c::VectorOfVariablesConstraint) = (MOI.VectorOfVariables(c.func), c.set)

function constraintobject(cr::ConstraintRef{Model}, ::Type{VariableRef}, ::Type{SetType}) where {SetType <: MOI.AbstractScalarSet}
f = MOI.get(cr.m, MOI.ConstraintFunction(), cr)::MOI.SingleVariable
s = MOI.get(cr.m, MOI.ConstraintSet(), cr)::SetType
return SingleVariableConstraint(VariableRef(cr.m, f), s)
end

function constraintobject(cr::ConstraintRef{Model}, ::Type{Vector{VariableRef}}, ::Type{SetType}) where {SetType <: MOI.AbstractVectorSet}
m = cr.m
f = MOI.get(m, MOI.ConstraintFunction(), cr)::MOI.VectorOfVariables
s = MOI.get(m, MOI.ConstraintSet(), cr)::SetType
return VectorOfVariablesConstraint(map(v -> VariableRef(m, v), f.variables), s)
function constraintobject(ref::ConstraintRef{Model, MOICON{FuncType, SetType}}) where
{FuncType <: MOI.SingleVariable, SetType <: MOI.AbstractScalarSet}
model = ref.m
f = MOI.get(model, MOI.ConstraintFunction(), ref)::FuncType
s = MOI.get(model, MOI.ConstraintSet(), ref)::SetType
return SingleVariableConstraint(VariableRef(model, f), s)
end

function constraintobject(ref::ConstraintRef{Model, MOICON{FuncType, SetType}}) where
{FuncType <: MOI.VectorOfVariables, SetType <: MOI.AbstractVectorSet}
model = ref.m
f = MOI.get(model, MOI.ConstraintFunction(), ref)::FuncType
s = MOI.get(model, MOI.ConstraintSet(), ref)::SetType
return VectorOfVariablesConstraint(map(v -> VariableRef(model, v), f.variables), s)
end


Expand Down
9 changes: 2 additions & 7 deletions test/JuMPExtension.jl
Original file line number Diff line number Diff line change
Expand Up @@ -114,13 +114,8 @@ function MOI.delete!(m::MyModel, cref::MyConstraintRef)
delete!(m.connames, cref.idx)
end
MOI.isvalid(m::MyModel, cref::MyConstraintRef) = cref.idx in keys(m.constraints)
function JuMP.constraintobject(cref::MyConstraintRef, F::Type, S::Type)
c = cref.model.constraints[cref.idx]
# `TypeError` should be thrown is `F` and `S` are not correct
# This is needed for the tests in `constraints.jl`
c.func::F
c.set::S
c
function JuMP.constraintobject(cref::MyConstraintRef)
return cref.model.constraints[cref.idx]
end

# Objective
Expand Down
63 changes: 27 additions & 36 deletions test/constraint.jl
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
function constraints_test(ModelType::Type{<:JuMP.AbstractModel}, VariableRefType::Type{<:JuMP.AbstractVariableRef}, ConstraintRefType::Type)
AffExprType = JuMP.GenericAffExpr{Float64, VariableRefType}
QuadExprType = JuMP.GenericQuadExpr{Float64, VariableRefType}

function constraints_test(ModelType::Type{<:JuMP.AbstractModel})
@testset "SingleVariable constraints" begin
m = ModelType()
@variable(m, x)
Expand All @@ -10,16 +7,14 @@ function constraints_test(ModelType::Type{<:JuMP.AbstractModel}, VariableRefType
# the LHS is first subtracted to form x - 10.0 <= 0.
@constraint(m, cref, x in MOI.LessThan(10.0))
@test JuMP.name(cref) == "cref"
c = JuMP.constraintobject(cref, VariableRefType, MOI.LessThan)
c = JuMP.constraintobject(cref)
@test c.func == x
@test c.set == MOI.LessThan(10.0)
@test_throws TypeError JuMP.constraintobject(cref, QuadExprType, MOI.LessThan)
@test_throws TypeError JuMP.constraintobject(cref, AffExprType, MOI.EqualTo)

@variable(m, y[1:2])
@constraint(m, cref2[i=1:2], y[i] in MOI.LessThan(float(i)))
@test JuMP.name(cref2[1]) == "cref2[1]"
c = JuMP.constraintobject(cref2[1], VariableRefType, MOI.LessThan)
c = JuMP.constraintobject(cref2[1])
@test c.func == y[1]
@test c.set == MOI.LessThan(1.0)
end
Expand All @@ -29,19 +24,17 @@ function constraints_test(ModelType::Type{<:JuMP.AbstractModel}, VariableRefType
@variable(m, x[1:2])

cref = @constraint(m, x in MOI.Zeros(2))
c = JuMP.constraintobject(cref, Vector{VariableRefType}, MOI.Zeros)
c = JuMP.constraintobject(cref)
@test c.func == x
@test c.set == MOI.Zeros(2)
@test_throws TypeError JuMP.constraintobject(cref, Vector{AffExprType}, MOI.Nonnegatives)
@test_throws TypeError JuMP.constraintobject(cref, AffExprType, MOI.EqualTo)

cref = @constraint(m, [x[2],x[1]] in MOI.Zeros(2))
c = JuMP.constraintobject(cref, Vector{VariableRefType}, MOI.Zeros)
c = JuMP.constraintobject(cref)
@test c.func == [x[2],x[1]]
@test c.set == MOI.Zeros(2)
end

@testset "AffExprType constraints" begin
@testset "AffExpr constraints" begin
m = ModelType()
@variable(m, x)

Expand All @@ -50,26 +43,24 @@ function constraints_test(ModelType::Type{<:JuMP.AbstractModel}, VariableRefType
JuMP.setname(cref, "c")
@test JuMP.name(cref) == "c"

c = JuMP.constraintobject(cref, AffExprType, MOI.LessThan)
c = JuMP.constraintobject(cref)
@test JuMP.isequal_canonical(c.func, 2x)
@test c.set == MOI.LessThan(10.0)
@test_throws TypeError JuMP.constraintobject(cref, QuadExprType, MOI.LessThan)
@test_throws TypeError JuMP.constraintobject(cref, AffExprType, MOI.EqualTo)

cref = @constraint(m, 3x + 1 10)
c = JuMP.constraintobject(cref, AffExprType, MOI.GreaterThan)
c = JuMP.constraintobject(cref)
@test JuMP.isequal_canonical(c.func, 3x)
@test c.set == MOI.GreaterThan(9.0)

cref = @constraint(m, 1 == -x)
c = JuMP.constraintobject(cref, AffExprType, MOI.EqualTo)
c = JuMP.constraintobject(cref)
@test JuMP.isequal_canonical(c.func, 1.0x)
@test c.set == MOI.EqualTo(-1.0)

@test_throws ErrorException @constraint(m, [x, 2x] == [1-x, 3])
@test_macro_throws ErrorException @constraint(m, [x == 1-x, 2x == 3])
cref = @constraint(m, [x, 2x] .== [1-x, 3])
c = JuMP.constraintobject.(cref, AffExprType, MOI.EqualTo)
c = JuMP.constraintobject.(cref)
@test JuMP.isequal_canonical(c[1].func, 2.0x)
@test c[1].set == MOI.EqualTo(1.0)
@test JuMP.isequal_canonical(c[2].func, 2.0x)
Expand All @@ -88,7 +79,7 @@ function constraints_test(ModelType::Type{<:JuMP.AbstractModel}, VariableRefType
@constraint(m, cref, 1.0 <= x + y + 1.0 <= 2.0)
@test JuMP.name(cref) == "cref"

c = JuMP.constraintobject(cref, AffExprType, MOI.Interval)
c = JuMP.constraintobject(cref)
@test JuMP.isequal_canonical(c.func, x + y)
@test c.set == MOI.Interval(0.0, 1.0)
end
Expand All @@ -103,10 +94,10 @@ function constraints_test(ModelType::Type{<:JuMP.AbstractModel}, VariableRefType
cref = @constraint(m, A*x .== b)
@test size(cref) == (2,)

c1 = JuMP.constraintobject(cref[1], AffExprType, MOI.EqualTo)
c1 = JuMP.constraintobject(cref[1])
@test JuMP.isequal_canonical(c1.func, x[1] + 2x[2])
@test c1.set == MOI.EqualTo(4.0)
c2 = JuMP.constraintobject(cref[2], AffExprType, MOI.EqualTo)
c2 = JuMP.constraintobject(cref[2])
@test JuMP.isequal_canonical(c2.func, 3x[1] + 4x[2])
@test c2.set == MOI.EqualTo(5.0)
end
Expand All @@ -121,8 +112,8 @@ function constraints_test(ModelType::Type{<:JuMP.AbstractModel}, VariableRefType
@test size(cref) == (2,2)
for i in 1:2
for j in 1:2
c = JuMP.constraintobject(cref[i,j], AffExprType, MOI.LessThan)
@test JuMP.isequal_canonical(c.func, convert(AffExprType, x[i,j]))
c = JuMP.constraintobject(cref[i,j])
@test JuMP.isequal_canonical(c.func, x[i,j] + 0)
@test c.set == MOI.LessThan(UB[i,j] - 1)
end
end
Expand All @@ -139,7 +130,7 @@ function constraints_test(ModelType::Type{<:JuMP.AbstractModel}, VariableRefType
@test size(cref) == (2,)

for i in 1:2
c = JuMP.constraintobject(cref[i], AffExprType, MOI.Interval)
c = JuMP.constraintobject(cref[i])
@test JuMP.isequal_canonical(c.func, x[i] + y[i])
@test c.set == MOI.Interval(l[i]-1, u[i]-1)
end
Expand All @@ -149,6 +140,7 @@ function constraints_test(ModelType::Type{<:JuMP.AbstractModel}, VariableRefType
m = ModelType()
@variable m x[1:2]
@constraint m cref1[i=2:4] x .== [i, i+1]
ConstraintRefType = eltype(cref1[2])
@test cref1 isa JuMP.JuMPArray{AbstractArray{ConstraintRefType}}
@constraint m cref2[i=1:3, j=1:4] x .≤ [i+j, i-j]
@test cref2 isa Matrix{AbstractArray{ConstraintRefType}}
Expand All @@ -157,25 +149,24 @@ function constraints_test(ModelType::Type{<:JuMP.AbstractModel}, VariableRefType
@test cref3 isa Vector{AbstractArray{ConstraintRefType}}
end

@testset "QuadExprType constraints" begin
@testset "QuadExpr constraints" begin
m = ModelType()
@variable(m, x)
@variable(m, y)

cref = @constraint(m, x^2 + x <= 1)
c = JuMP.constraintobject(cref, QuadExprType, MOI.LessThan)
c = JuMP.constraintobject(cref)
@test JuMP.isequal_canonical(c.func, x^2 + x)
@test c.set == MOI.LessThan(1.0)

cref = @constraint(m, y*x - 1.0 == 0.0)
c = JuMP.constraintobject(cref, QuadExprType, MOI.EqualTo)
c = JuMP.constraintobject(cref)
@test JuMP.isequal_canonical(c.func, x*y)
@test c.set == MOI.EqualTo(1.0)
@test_throws TypeError JuMP.constraintobject(cref, QuadExprType, MOI.LessThan)
@test_throws TypeError JuMP.constraintobject(cref, AffExprType, MOI.EqualTo)

# TODO: VectorQuadraticFunctions
# cref = @constraint(m, [x^2 - 1] in MOI.SecondOrderCone(1))
# c = JuMP.constraintobject(cref, QuadExprType, MOI.SecondOrderCone)
# c = JuMP.constraintobject(cref)
# @test JuMP.isequal_canonical(c.func, -1 + x^2)
# @test c.set == MOI.SecondOrderCone(1)
end
Expand All @@ -188,13 +179,13 @@ function constraints_test(ModelType::Type{<:JuMP.AbstractModel}, VariableRefType
@variable(m, w)

cref = @constraint(m, [x y; z w] in PSDCone())
c = JuMP.constraintobject(cref, Vector{VariableRefType}, MOI.PositiveSemidefiniteConeSquare)
c = JuMP.constraintobject(cref)
@test c.func == [x, z, y, w]
@test c.set == MOI.PositiveSemidefiniteConeSquare(2)

@SDconstraint(m, cref, [x 1; 1 -y] [1 x; x -2])
@test JuMP.name(cref) == "cref"
c = JuMP.constraintobject(cref, Vector{AffExprType}, MOI.PositiveSemidefiniteConeTriangle)
c = JuMP.constraintobject(cref)
@test JuMP.isequal_canonical(c.func[1], x-1)
@test JuMP.isequal_canonical(c.func[2], 1-x)
@test JuMP.isequal_canonical(c.func[3], 2-y)
Expand All @@ -203,7 +194,7 @@ function constraints_test(ModelType::Type{<:JuMP.AbstractModel}, VariableRefType
@SDconstraint(m, iref[i=1:2], 0 [x+i x+y; x+y -y])
for i in 1:2
@test JuMP.name(iref[i]) == "iref[$i]"
c = JuMP.constraintobject(iref[i], Vector{AffExprType}, MOI.PositiveSemidefiniteConeTriangle)
c = JuMP.constraintobject(iref[i])
@test JuMP.isequal_canonical(c.func[1], x+i)
@test JuMP.isequal_canonical(c.func[2], x+y)
@test JuMP.isequal_canonical(c.func[3], -y)
Expand Down Expand Up @@ -251,9 +242,9 @@ function constraints_test(ModelType::Type{<:JuMP.AbstractModel}, VariableRefType
end

@testset "Constraints for JuMP.Model" begin
constraints_test(Model, VariableRef, ConstraintRef{Model})
constraints_test(Model)
end

@testset "Constraints for JuMPExtension.MyModel" begin
constraints_test(JuMPExtension.MyModel, JuMPExtension.MyVariableRef, JuMPExtension.MyConstraintRef)
constraints_test(JuMPExtension.MyModel)
end
20 changes: 9 additions & 11 deletions test/macros.jl
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,6 @@ end
end

function macros_test(ModelType::Type{<:JuMP.AbstractModel}, VariableRefType::Type{<:JuMP.AbstractVariableRef})
AffExprType = JuMP.GenericAffExpr{Float64, VariableRefType}

@testset "buildconstraint on variable" begin
m = ModelType()
@variable(m, x)
Expand All @@ -91,42 +89,42 @@ function macros_test(ModelType::Type{<:JuMP.AbstractModel}, VariableRefType::Typ
t = 10.0

cref = @constraint(m, 3x - y == 3.3(w + 2z) + 5)
c = JuMP.constraintobject(cref, AffExprType, MOI.EqualTo)
c = JuMP.constraintobject(cref)
@test JuMP.isequal_canonical(c.func, 3*x - y - 3.3*w - 6.6*z)
@test c.set == MOI.EqualTo(5.0)

cref = @constraint(m, 3x - y == (w + 2z)*3.3 + 5)
c = JuMP.constraintobject(cref, AffExprType, MOI.EqualTo)
c = JuMP.constraintobject(cref)
@test JuMP.isequal_canonical(c.func, 3*x - y - 3.3*w - 6.6*z)
@test c.set == MOI.EqualTo(5.0)

cref = @constraint(m, (x+y)/2 == 1)
c = JuMP.constraintobject(cref, AffExprType, MOI.EqualTo)
c = JuMP.constraintobject(cref)
@test JuMP.isequal_canonical(c.func, 0.5*x + 0.5*y)
@test c.set == MOI.EqualTo(1.0)

cref = @constraint(m, -1 <= x-y <= t)
c = JuMP.constraintobject(cref, AffExprType, MOI.Interval)
c = JuMP.constraintobject(cref)
@test JuMP.isequal_canonical(c.func, x - y)
@test c.set == MOI.Interval(-1.0, t)

cref = @constraint(m, -1 <= x+1 <= 1)
c = JuMP.constraintobject(cref, AffExprType, MOI.Interval)
c = JuMP.constraintobject(cref)
@test JuMP.isequal_canonical(c.func, 1x)
@test c.set == MOI.Interval(-2.0, 0.0)

cref = @constraint(m, -1 <= x <= 1)
c = JuMP.constraintobject(cref, VariableRefType, MOI.Interval)
c = JuMP.constraintobject(cref)
@test c.func == x
@test c.set == MOI.Interval(-1.0, 1.0)

cref = @constraint(m, -1 <= x <= sum(0.5 for i = 1:2))
c = JuMP.constraintobject(cref, VariableRefType, MOI.Interval)
c = JuMP.constraintobject(cref)
@test c.func == x
@test c.set == MOI.Interval(-1.0, 1.0)

cref = @constraint(m, 1 >= x >= 0)
c = JuMP.constraintobject(cref, VariableRefType, MOI.Interval)
c = JuMP.constraintobject(cref)
@test c.func == x
@test c.set == MOI.Interval(0.0, 1.0)

Expand All @@ -138,7 +136,7 @@ function macros_test(ModelType::Type{<:JuMP.AbstractModel}, VariableRefType::Typ
@test JuMP.isequal_canonical(@expression(m, quad, (w+3)*(2x+1)+10), 2*w*x + 6*x + w + 13)

cref = @constraint(m, 3 + 5*7 <= 0)
c = JuMP.constraintobject(cref, AffExpr, MOI.LessThan)
c = JuMP.constraintobject(cref)
@test JuMP.isequal_canonical(c.func, zero(AffExpr))
@test c.set == MOI.LessThan(-38.0)
end
Expand Down
Loading

0 comments on commit f656a57

Please sign in to comment.