Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ CodecZlib = "944b1d66-785c-5afd-91f1-9de20f533193"
DataStructures = "864edb3b-99cc-5e75-8d2d-829cb0a9cfe8"
ForwardDiff = "f6369f11-7733-5829-9624-2563aa707210"
JSON = "682c06a0-de6a-54ab-a142-c8b1cf79cde6"
JSONSchema = "7d188eb4-7ad8-530c-ae41-71a32a6d4692"
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
MutableArithmetics = "d8a4904e-b15c-11e9-3269-09a3773c0cb0"
NaNMath = "77ba4419-2d1f-58cd-9bb1-8ffee604a2e3"
Expand Down
62 changes: 52 additions & 10 deletions src/FileFormats/MOF/read.jl
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,48 @@ function Base.read!(io::IO, model::Model)
name_map = read_variables(model, object)
read_objective(model, object, name_map)
read_constraints(model, object, name_map)
_convert_to_nlpblock(model)
return
end

function _convert_to_nlpblock(model::Model)
has_constraints = false
nlp_model = MOI.Nonlinear.Model()
for S in (
MOI.LessThan{Float64},
MOI.GreaterThan{Float64},
MOI.EqualTo{Float64},
MOI.Interval{Float64},
)
for ci in MOI.get(model, MOI.ListOfConstraintIndices{Nonlinear,S}())
f = MOI.get(model, MOI.ConstraintFunction(), ci)
set = MOI.get(model, MOI.ConstraintSet(), ci)
MOI.Nonlinear.add_constraint(nlp_model, f.expr, set)
# We don't need this in `model` any more.
MOI.delete(model, ci)
has_constraints = true
end
end
if MOI.get(model, MOI.ObjectiveFunctionType()) == Nonlinear
obj = MOI.get(model, MOI.ObjectiveFunction{Nonlinear}())
MOI.Nonlinear.set_objective(nlp_model, obj.expr)
MOI.set(
model,
MOI.ObjectiveFunction{MOI.ScalarAffineFunction{Float64}}(),
MOI.ScalarAffineFunction{Float64}(
MOI.ScalarAffineTerm{Float64}[],
0.0,
),
)
end
if has_constraints
evaluator = MOI.Nonlinear.Evaluator(
nlp_model,
MOI.Nonlinear.SparseReverseMode(),
MOI.get(model, MOI.ListOfVariableIndices()),
)
MOI.set(model, MOI.NLPBlock(), MOI.NLPBlockData(evaluator))
end
return
end

Expand Down Expand Up @@ -357,27 +399,27 @@ end
# ========== Typed scalar sets ==========

function set_to_moi(::Val{:LessThan}, object::Object)
return MOI.LessThan(object["upper"])
return MOI.LessThan{Float64}(object["upper"])
end

function set_to_moi(::Val{:GreaterThan}, object::Object)
return MOI.GreaterThan(object["lower"])
return MOI.GreaterThan{Float64}(object["lower"])
end

function set_to_moi(::Val{:EqualTo}, object::Object)
return MOI.EqualTo(object["value"])
return MOI.EqualTo{Float64}(object["value"])
end

function set_to_moi(::Val{:Interval}, object::Object)
return MOI.Interval(object["lower"], object["upper"])
return MOI.Interval{Float64}(object["lower"], object["upper"])
end

function set_to_moi(::Val{:Semiinteger}, object::Object)
return MOI.Semiinteger(object["lower"], object["upper"])
return MOI.Semiinteger{Float64}(object["lower"], object["upper"])
end

function set_to_moi(::Val{:Semicontinuous}, object::Object)
return MOI.Semicontinuous(object["lower"], object["upper"])
return MOI.Semicontinuous{Float64}(object["lower"], object["upper"])
end

# ========== Non-typed vector sets ==========
Expand Down Expand Up @@ -469,19 +511,19 @@ end
# ========== Typed vector sets ==========

function set_to_moi(::Val{:PowerCone}, object::Object)
return MOI.PowerCone(object["exponent"]::Float64)
return MOI.PowerCone{Float64}(object["exponent"])
end

function set_to_moi(::Val{:DualPowerCone}, object::Object)
return MOI.DualPowerCone(object["exponent"]::Float64)
return MOI.DualPowerCone{Float64}(object["exponent"])
end

function set_to_moi(::Val{:SOS1}, object::Object)
return MOI.SOS1(Float64.(object["weights"]))
return MOI.SOS1(convert(Vector{Float64}, object["weights"]))
end

function set_to_moi(::Val{:SOS2}, object::Object)
return MOI.SOS2(Float64.(object["weights"]))
return MOI.SOS2(convert(Vector{Float64}, object["weights"]))
end

# :IndicatorSet is required for v0.6
Expand Down
37 changes: 28 additions & 9 deletions test/FileFormats/MOF/MOF.jl
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,28 @@ function test_HS071()
MOI.write_to_file(model, TEST_MOF_FILE)
@test replace(read(TEST_MOF_FILE, String), '\r' => "") ==
replace(read(joinpath(@__DIR__, "nlp.mof.json"), String), '\r' => "")
return _validate(TEST_MOF_FILE)
_validate(TEST_MOF_FILE)
return
end

function test_read_HS071()
model = MOF.Model()
MOI.read_from_file(model, joinpath(@__DIR__, "nlp.mof.json"))
@test MOI.get(model, MOI.ListOfConstraintTypesPresent()) ==
Tuple{Type,Type}[(MOI.VariableIndex, MOI.Interval{Float64})]
x = MOI.get(model, MOI.ListOfVariableIndices())
@test length(x) == 4
@test MOI.get(model, MOI.VariableName(), x) == ["var_$i" for i in 1:4]
block = MOI.get(model, MOI.NLPBlock())
evaluator = block.evaluator
MOI.initialize(evaluator, [:ExprGraph])
hs071_block = HS071(x)
hs071 = hs071_block.evaluator
@test MOI.objective_expr(evaluator) == MOI.objective_expr(hs071)
for i in 1:2
@test MOI.constraint_expr(evaluator, i) == MOI.constraint_expr(hs071, i)
end
return
end

function test_nonlinear_error_handling()
Expand Down Expand Up @@ -206,7 +227,6 @@ function test_Roundtrip_nonlinear_expressions()
end

function test_nonlinear_readingwriting()
# Write to file.
model = MOF.Model()
(x, y) = MOI.add_variables(model, 2)
MOI.set(model, MOI.VariableName(), x, "var_x")
Expand All @@ -221,13 +241,12 @@ function test_nonlinear_readingwriting()
# Read the model back in.
model2 = MOF.Model()
MOI.read_from_file(model2, TEST_MOF_FILE)
con2 = MOI.get(model2, MOI.ConstraintIndex, "con")
foo2 = MOI.get(model2, MOI.ConstraintFunction(), con2)
# Test that we recover the constraint.
@test foo2.expr == :(2 * $x + sin($x)^2 - $y)
@test MOI.get(model, MOI.ConstraintSet(), con) ==
MOI.get(model2, MOI.ConstraintSet(), con2)
return _validate(TEST_MOF_FILE)
block = MOI.get(model2, MOI.NLPBlock())
MOI.initialize(block.evaluator, [:ExprGraph])
@test MOI.constraint_expr(block.evaluator, 1) ==
:(2 * x[$x] + sin(x[$x])^2 - x[$y] == 1.0)
_validate(TEST_MOF_FILE)
return
end

function test_show()
Expand Down