Skip to content

Commit

Permalink
Merge pull request jump-dev#1583 from JuliaOpt/bl/jumpextprintcon
Browse files Browse the repository at this point in the history
✅ Implement printing for JuMPExt constraint ef
  • Loading branch information
blegat authored Nov 6, 2018
2 parents d338581 + 9cb4a69 commit 3b9dacc
Show file tree
Hide file tree
Showing 2 changed files with 104 additions and 91 deletions.
47 changes: 25 additions & 22 deletions test/JuMPExtension.jl
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,26 @@ using MathOptInterface
const MOI = MathOptInterface
using JuMP

struct ConstraintIndex
value::Int # Index in `model.constraints`
end

mutable struct MyModel <: JuMP.AbstractModel
nextvaridx::Int # Next variable index is nextvaridx+1
variables::Dict{Int, JuMP.ScalarVariable} # Map varidx -> variable
varnames::Dict{Int, String} # Map varidx -> name
nextconidx::Int # Next constraint index is nextconidx+1
constraints::Dict{Int, JuMP.AbstractConstraint} # Map conidx -> variable
connames::Dict{Int, String} # Map varidx -> name
constraints::Dict{ConstraintIndex,
JuMP.AbstractConstraint} # Map conidx -> variable
connames::Dict{ConstraintIndex, String} # Map conidx -> name
objectivesense::MOI.OptimizationSense
objective_function::JuMP.AbstractJuMPScalar
obj_dict::Dict{Symbol, Any} # Same that JuMP.Model's field `obj_dict`
function MyModel()
new(0, Dict{Int, JuMP.AbstractVariable}(), Dict{Int, String}(), # Variables
0, Dict{Int, JuMP.AbstractConstraint}(), Dict{Int, String}(), # Constraints
new(0, Dict{Int, JuMP.AbstractVariable}(),
Dict{Int, String}(), # Variables
0, Dict{ConstraintIndex, JuMP.AbstractConstraint}(),
Dict{ConstraintIndex, String}(), # Constraints
MOI.FeasibilitySense, zero(JuMP.GenericAffExpr{Float64, MyVariableRef}),
Dict{Symbol, Any}())
end
Expand Down Expand Up @@ -185,32 +192,28 @@ function JuMP.unset_integer(vref::MyVariableRef)
end

# Constraints
struct MyConstraintRef
model::MyModel # `model` owning the constraint
idx::Int # Index in `model.constraints`
end
const MyConstraintRef = JuMP.ConstraintRef{MyModel, ConstraintIndex}
JuMP.constraint_type(::MyModel) = MyConstraintRef
if VERSION >= v"0.7-"
Base.broadcastable(cref::MyConstraintRef) = Ref(cref)
end
function JuMP.add_constraint(m::MyModel, c::JuMP.AbstractConstraint, name::String="")
m.nextconidx += 1
cref = MyConstraintRef(m, m.nextconidx)
m.constraints[cref.idx] = c
function JuMP.add_constraint(model::MyModel, c::JuMP.AbstractConstraint,
name::String="")
model.nextconidx += 1
index = ConstraintIndex(model.nextconidx)
cref = JuMP.ConstraintRef(model, index, JuMP.shape(c))
model.constraints[index] = c
JuMP.set_name(cref, name)
cref
return cref
end
function JuMP.delete(model::MyModel, constraint_ref::MyConstraintRef)
@assert JuMP.is_valid(model, constraint_ref)
delete!(model.constraints, constraint_ref.idx)
delete!(model.connames, constraint_ref.idx)
delete!(model.constraints, constraint_ref.index)
delete!(model.connames, constraint_ref.index)
end
function JuMP.is_valid(model::MyModel, constraint_ref::MyConstraintRef)
return (model === constraint_ref.model &&
constraint_ref.idx in keys(model.constraints))
constraint_ref.index in keys(model.constraints))
end
function JuMP.constraint_object(cref::MyConstraintRef)
return cref.model.constraints[cref.idx]
return cref.model.constraints[cref.index]
end

# Objective
Expand Down Expand Up @@ -240,9 +243,9 @@ JuMP.name(vref::MyVariableRef) = vref.model.varnames[vref.idx]
function JuMP.set_name(vref::MyVariableRef, name::String)
vref.model.varnames[vref.idx] = name
end
JuMP.name(cref::MyConstraintRef) = cref.model.connames[cref.idx]
JuMP.name(cref::MyConstraintRef) = cref.model.connames[cref.index]
function JuMP.set_name(cref::MyConstraintRef, name::String)
cref.model.connames[cref.idx] = name
cref.model.connames[cref.index] = name
end

end
148 changes: 79 additions & 69 deletions test/print.jl
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,79 @@ Base.isless(u::UnitNumber, v::UnitNumber) = isless(u.α, v.α)
io_test(IJuliaMode, ex, "-2 x_{1}\\times z + x_{1}\\times x_{2}")
end

# See https://github.com/JuliaOpt/JuMP.jl/pull/1352
@testset "Expression of coefficient type with unit" begin
m = Model()
@variable m x
@variable m y
u = UnitNumber(2.0)
aff = JuMP.GenericAffExpr(zero(u), x => u, y => zero(u))
io_test(REPLMode, aff, "UnitNumber(2.0) x")
io_test(IJuliaMode, aff, "UnitNumber(2.0) x")
quad = aff * x
io_test(REPLMode, quad, "UnitNumber(2.0) x² + UnitNumber(0.0)")
io_test(IJuliaMode, quad, "UnitNumber(2.0) x^2 + UnitNumber(0.0)")
end

@testset "Nonlinear expressions" begin
model = Model()
@variable(model, x)
expr = @NLexpression(model, x + 1)
io_test(REPLMode, expr, "\"Reference to nonlinear expression #1\"")
end

@testset "Nonlinear parameters" begin
model = Model()
@NLparameter(model, param == 1.0)
io_test(REPLMode, param, "\"Reference to nonlinear parameter #1\"")
end

@testset "NLPEvaluator" begin
model = Model()
evaluator = JuMP.NLPEvaluator(model)
io_test(REPLMode, evaluator, "\"A JuMP.NLPEvaluator\"")
end

@testset "Nonlinear constraints" begin
le = JuMP.math_symbol(REPLMode, :leq)
ge = JuMP.math_symbol(REPLMode, :geq)
eq = JuMP.math_symbol(REPLMode, :eq)

model = Model()
@variable(model, x)
constr_le = @NLconstraint(model, sin(x) <= 1)
constr_ge = @NLconstraint(model, sin(x) >= 1)
constr_eq = @NLconstraint(model, sin(x) == 1)
constr_range = @NLconstraint(model, 0 <= sin(x) <= 1)

io_test(REPLMode, constr_le, "sin(x) - 1.0 $le 0")
io_test(REPLMode, constr_ge, "sin(x) - 1.0 $ge 0")
io_test(REPLMode, constr_eq, "sin(x) - 1.0 $eq 0")
# Note: This is inconsistent with the "x in [-1, 1]" printing for
# regular constraints.
io_test(REPLMode, constr_range, "0 $le sin(x) $le 1")

io_test(IJuliaMode, constr_le, "sin(x) - 1.0 \\leq 0")
io_test(IJuliaMode, constr_ge, "sin(x) - 1.0 \\geq 0")
io_test(IJuliaMode, constr_eq, "sin(x) - 1.0 = 0")
io_test(IJuliaMode, constr_range, "0 \\leq sin(x) \\leq 1")
end

@testset "Nonlinear constraints with embedded parameters/expressions" begin
le = JuMP.math_symbol(REPLMode, :leq)

model = Model()
@variable(model, x)
expr = @NLexpression(model, x + 1)
@NLparameter(model, param == 1.0)

constr = @NLconstraint(model, expr - param <= 0)
io_test(REPLMode, constr, "(subexpression[1] - parameter[1]) - 0.0 $le 0")
io_test(IJuliaMode, constr, "(subexpression_{1} - parameter_{1}) - 0.0 \\leq 0")
end
end

function printing_test(ModelType::Type{<:JuMP.AbstractModel})
@testset "VariableRef" begin
m = Model()
@variable(m, 0 <= x <= 2)
Expand Down Expand Up @@ -144,20 +217,6 @@ Base.isless(u::UnitNumber, v::UnitNumber) = isless(u.α, v.α)
io_test(IJuliaMode, w[1,3], "symm_{1,3}")
end

# See https://github.com/JuliaOpt/JuMP.jl/pull/1352
@testset "Expression of coefficient type with unit" begin
m = Model()
@variable m x
@variable m y
u = UnitNumber(2.0)
aff = JuMP.GenericAffExpr(zero(u), x => u, y => zero(u))
io_test(REPLMode, aff, "UnitNumber(2.0) x")
io_test(IJuliaMode, aff, "UnitNumber(2.0) x")
quad = aff * x
io_test(REPLMode, quad, "UnitNumber(2.0) x² + UnitNumber(0.0)")
io_test(IJuliaMode, quad, "UnitNumber(2.0) x^2 + UnitNumber(0.0)")
end

@testset "SingleVariable constraints" begin
ge = JuMP.math_symbol(REPLMode, :geq)
in_sym = JuMP.math_symbol(REPLMode, :in)
Expand Down Expand Up @@ -240,61 +299,12 @@ Base.isless(u::UnitNumber, v::UnitNumber) = isless(u.α, v.α)
io_test(REPLMode, quad_constr, "2 x$sq $le 1.0")
# TODO: Test in IJulia mode.
end
end

@testset "Nonlinear expressions" begin
model = Model()
@variable(model, x)
expr = @NLexpression(model, x + 1)
io_test(REPLMode, expr, "\"Reference to nonlinear expression #1\"")
end

@testset "Nonlinear parameters" begin
model = Model()
@NLparameter(model, param == 1.0)
io_test(REPLMode, param, "\"Reference to nonlinear parameter #1\"")
end

@testset "NLPEvaluator" begin
model = Model()
evaluator = JuMP.NLPEvaluator(model)
io_test(REPLMode, evaluator, "\"A JuMP.NLPEvaluator\"")
end

@testset "Nonlinear constraints" begin
le = JuMP.math_symbol(REPLMode, :leq)
ge = JuMP.math_symbol(REPLMode, :geq)
eq = JuMP.math_symbol(REPLMode, :eq)

model = Model()
@variable(model, x)
constr_le = @NLconstraint(model, sin(x) <= 1)
constr_ge = @NLconstraint(model, sin(x) >= 1)
constr_eq = @NLconstraint(model, sin(x) == 1)
constr_range = @NLconstraint(model, 0 <= sin(x) <= 1)

io_test(REPLMode, constr_le, "sin(x) - 1.0 $le 0")
io_test(REPLMode, constr_ge, "sin(x) - 1.0 $ge 0")
io_test(REPLMode, constr_eq, "sin(x) - 1.0 $eq 0")
# Note: This is inconsistent with the "x in [-1, 1]" printing for
# regular constraints.
io_test(REPLMode, constr_range, "0 $le sin(x) $le 1")

io_test(IJuliaMode, constr_le, "sin(x) - 1.0 \\leq 0")
io_test(IJuliaMode, constr_ge, "sin(x) - 1.0 \\geq 0")
io_test(IJuliaMode, constr_eq, "sin(x) - 1.0 = 0")
io_test(IJuliaMode, constr_range, "0 \\leq sin(x) \\leq 1")
end

@testset "Nonlinear constraints with embedded parameters/expressions" begin
le = JuMP.math_symbol(REPLMode, :leq)

model = Model()
@variable(model, x)
expr = @NLexpression(model, x + 1)
@NLparameter(model, param == 1.0)
@testset "Printing for JuMP.Model" begin
printing_test(Model)
end

constr = @NLconstraint(model, expr - param <= 0)
io_test(REPLMode, constr, "(subexpression[1] - parameter[1]) - 0.0 $le 0")
io_test(IJuliaMode, constr, "(subexpression_{1} - parameter_{1}) - 0.0 \\leq 0")
end
@testset "Printing for JuMPExtension.MyModel" begin
printing_test(JuMPExtension.MyModel)
end

0 comments on commit 3b9dacc

Please sign in to comment.