Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
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
8 changes: 6 additions & 2 deletions .ci/ci.jl
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
rm("Manifest.toml";force=true)

rm(joinpath(@__DIR__, "Project.toml");force=true)
rm(joinpath(@__DIR__, "Manifest.toml");force=true)

using Pkg

Pkg.activate(@__DIR__)

if ARGS[1] == "full"
pkgs = ["MadNLPHSL","MadNLPPardiso","MadNLPMumps","MadNLPGPU","MadNLPGraph","MadNLPKrylov"]
pkgs = ["MadNLPHSL","MadNLPPardiso","MadNLPMumps","MadNLPGraph","MadNLPKrylov"]
elseif ARGS[1] == "basic"
pkgs = ["MadNLPMumps","MadNLPGraph","MadNLPKrylov"]
else
Expand Down
6 changes: 2 additions & 4 deletions Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,20 +17,18 @@ SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf"
SuiteSparse = "4607b0f0-06f3-5cda-b6b1-a6196a1729e9"

[compat]
AmplNLReader = "~0.11"
MINLPTests = "~0.5"
MadNLPTests = "~0.3"
MathOptInterface = "~0.9"
MathOptInterface = "0.10.5 - 0.10.8"
NLPModels = "~0.17.2, 0.18"
SolverCore = "~0.1,~0.2"
julia = "1.3"

[extras]
AmplNLReader = "77dd3d4c-cb1d-5e09-9340-85030ff7ba66"
MINLPTests = "ee0a3090-8ee9-5cdb-b8cb-8eeba3165522"
MadNLPTests = "b52a2a03-04ab-4a5f-9698-6a2deff93217"
Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"

[targets]
test = ["Test", "MadNLPTests", "AmplNLReader", "MINLPTests", "Random"]
test = ["Test", "MadNLPTests", "MINLPTests", "Random"]
2 changes: 1 addition & 1 deletion lib/MadNLPGraph/Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ Metis = "2679e427-3c69-5b7f-982b-ece356f1e94b"

[compat]
MadNLP = "~0.3"
JuMP = "~0.21"
JuMP = "~0.22"
Plasmo = "~0.4"
LightGraphs = "~1.3"
Metis = "1"
Expand Down
2 changes: 1 addition & 1 deletion lib/MadNLPGraph/src/MadNLPGraph.jl
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import MadNLP:
get_lcon, get_ucon, jac_structure!, hess_structure!, obj, grad!, cons!, jac_coord!, hess_coord!
import Metis: partition
import LightGraphs: Graph, Edge, add_edge!, edges, src, dst, neighbors, nv
import Plasmo: OptiGraph, OptiNode, OptiEdge, all_nodes, all_edges, all_variables, num_all_nodes, getlinkconstraints, getnode, num_variables, num_constraints
import Plasmo: OptiGraph, OptiNode, OptiEdge, all_nodes, all_edges, all_variables, num_all_nodes, link_constraints, getnode, num_variables, num_constraints
import JuMP: _create_nlp_block_data, set_optimizer, GenericAffExpr

include("plasmo_interface.jl")
Expand Down
10 changes: 7 additions & 3 deletions lib/MadNLPGraph/src/plasmo_interface.jl
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ end

function jacobian_structure(linkedge::OptiEdge,I,J,ninds,x_index_map,g_index_map)
offset=1
for linkcon in getlinkconstraints(linkedge)
for linkcon in link_constraints(linkedge)
offset += jacobian_structure(linkcon,I,J,ninds,x_index_map,g_index_map,offset)
end
end
Expand Down Expand Up @@ -107,7 +107,7 @@ function eval_function(aff::GenericAffExpr,x,ninds,x_index_map)
end
function eval_constraint(linkedge::OptiEdge,c,x,ninds,x_index_map)
cnt = 1
for linkcon in getlinkconstraints(linkedge)
for linkcon in link_constraints(linkedge)
c[cnt] = eval_function(get_func(linkcon),x,ninds,x_index_map)
cnt += 1
end
Expand All @@ -134,7 +134,7 @@ end

function eval_constraint_jacobian(linkedge::OptiEdge,jac,x)
offset=0
for linkcon in getlinkconstraints(linkedge)
for linkcon in link_constraints(linkedge)
offset+=eval_constraint_jacobian(linkcon,jac,offset)
end
end
Expand Down Expand Up @@ -400,5 +400,9 @@ function optimize!(graph::OptiGraph; option_dict = Dict{Symbol,Any}(), kwargs...
view(result.multipliers_L,nlp.ninds[k]),
view(result.multipliers_U,nlp.ninds[k]),
ips.cnt.k, ips.nlp.counters,ips.cnt.total_time)
# TODO: quick hack to specify to JuMP that the
# model is not dirty (so we do not run in `OptimizeNotCalled`
# exception).
nlp.modelnodes[k].model.is_model_dirty = false
end
end
2 changes: 1 addition & 1 deletion lib/MadNLPTests/Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"

[compat]
JuMP = "~0.21"
JuMP = "~0.22"
MadNLP = "~0.3"
NLPModels = "~0.17.2, 0.18"
julia = "1.3"
207 changes: 108 additions & 99 deletions src/Interfaces/MOI_interface.jl

Large diffs are not rendered by default.

194 changes: 76 additions & 118 deletions test/MOI_interface_test.jl
Original file line number Diff line number Diff line change
@@ -1,130 +1,88 @@
using MathOptInterface
const MOI = MathOptInterface
const MOIT = MOI.Test
const MOIU = MOI.Utilities
const MOIB = MOI.Bridges
module TestMOIWrapper

const config = MOIT.TestConfig(atol=1e-4, rtol=1e-4,
optimal_status=MOI.LOCALLY_SOLVED)
const config_no_duals = MOIT.TestConfig(atol=1e-4, rtol=1e-4, duals=false,
optimal_status=MOI.LOCALLY_SOLVED)
using MadNLP
using Test

@testset "MOI utils" begin
optimizer = MadNLP.Optimizer()
@testset "SolverName" begin
@test MOI.get(optimizer, MOI.SolverName()) == "MadNLP"
end
@testset "supports_default_copy_to" begin
@test MOIU.supports_default_copy_to(optimizer, false)
@test !MOIU.supports_default_copy_to(optimizer, true)
end
@testset "MOI.Silent" begin
@test MOI.supports(optimizer, MOI.Silent())
@test MOI.get(optimizer, MOI.Silent()) == false
MOI.set(optimizer, MOI.Silent(), true)
@test MOI.get(optimizer, MOI.Silent()) == true
end
@testset "MOI.TimeLimitSec" begin
@test MOI.supports(optimizer, MOI.TimeLimitSec())
my_time_limit = 10.
MOI.set(optimizer, MOI.TimeLimitSec(), my_time_limit)
@test MOI.get(optimizer, MOI.TimeLimitSec()) == my_time_limit
end
@testset "MOI.MaxIter" begin
MOI.set(optimizer,MOI.RawParameter("max_iter"),1)
@test MOI.get(optimizer,MOI.RawParameter("max_iter")) == 1
const MOI = MadNLP.MathOptInterface

function runtests()
for name in names(@__MODULE__; all = true)
if startswith("$(name)", "test_")
@testset "$(name)" begin
getfield(@__MODULE__, name)()
end
end
end
return
end

@testset "Testing getters" begin
MOIT.copytest(MOI.instantiate(()->MadNLP.Optimizer(print_level=MadNLP.ERROR),
with_bridge_type=Float64), MOIU.Model{Float64}())
end
function test_MOI_Test()
model = MOI.Bridges.full_bridge_optimizer(
MOI.Utilities.CachingOptimizer(
MOI.Utilities.UniversalFallback(MOI.Utilities.Model{Float64}()),
MadNLP.Optimizer(),
),
Float64,
)
MOI.set(model, MOI.Silent(), true)
MOI.Test.runtests(
model,
MOI.Test.Config(
atol = 1e-4,
rtol = 1e-4,
optimal_status = MOI.LOCALLY_SOLVED,
exclude = Any[
MOI.delete,
MOI.ConstraintDual,
MOI.ConstraintBasisStatus,
MOI.DualObjectiveValue,
MOI.ObjectiveBound,
]
);
exclude = String[
"test_modification",
# - Need to implement TimeLimitSec
"test_attribute_TimeLimitSec",
# - Wrong return type
"test_model_UpperBoundAlreadySet",
# - Final objective value is not equal to 0.0
"test_objective_FEASIBILITY_SENSE_clears_objective",

@testset "Bounds set twice" begin
optimizer = MadNLP.Optimizer(print_level=MadNLP.ERROR)
MOIT.set_lower_bound_twice(optimizer, Float64)
MOIT.set_upper_bound_twice(optimizer, Float64)
end
# TODO: Need to investigate why these tests are breaking
# get(model, MOI.ConstraintPrimal(), c) returns the
# opposite value: if 1.0 is expected, -1.0 is returned
"test_constraint_ScalarAffineFunction_EqualTo",
"test_quadratic_nonconvex_constraint_basic",
"test_linear_integration",

@testset "MOI Linear tests" begin
optimizer = MadNLP.Optimizer(print_level=MadNLP.ERROR)
exclude = ["linear1", # modify constraints not allowed
"linear5", # modify constraints not allowed
"linear6", # constraint set for l/q not allowed
"linear7", # VectorAffineFunction not supported.
"linear8a", # Behavior in infeasible case doesn't match test.
"linear8b", # Behavior in unbounded case doesn't match test.
"linear8c", # Behavior in unbounded case doesn't match test.
"linear10", # Interval not supported yet
"linear10b", # Interval not supported yet
"linear11", # Variable cannot be deleted
"linear12", # Behavior in infeasible case doesn't match test.
"linear14", # Variable cannot be deleted
"linear15", # VectorAffineFunction not supported.
]
MOIT.contlineartest(optimizer, config_no_duals,exclude)
end
# TODO: there might be an issue with VectorAffineFunction/VectorOfVariables
"test_conic_NormOneCone_VectorOfVariables",
"test_conic_NormOneCone_VectorAffineFunction",
"test_conic_NormInfinityCone_VectorOfVariables",
"test_conic_NormInfinityCone_VectorAffineFunction",
"test_conic_linear_VectorAffineFunction",
"test_conic_linear_VectorOfVariables",

@testset "MOI NLP tests" begin
optimizer = MadNLP.Optimizer(print_level=MadNLP.ERROR)
exclude = [
"feasibility_sense_with_objective_and_no_hessian", # we need Hessians
"feasibility_sense_with_no_objective_and_no_hessian", # we need Hessians
"hs071_no_hessian", # we need Hessians
"hs071_hessian_vector_product_test", # Hessian-vector product is needed
]
MOIT.nlptest(optimizer,config,exclude)
end
# Tests excluded on purpose
# - Excluded as MadNLP returns LOCALLY_INFEASIBLE instead of INFEASIBLE
"INFEASIBLE",
"test_solve_DualStatus_INFEASIBILITY_CERTIFICATE_",
# - Excluded because Hessian information is needed
"test_nonlinear_hs071_hessian_vector_product",
# - Excluded because Hessian information is needed
"test_nonlinear_hs071_no_hessian",
# - Excluded because Hessian information is needed
"test_nonlinear_invalid",

@testset "Unit" begin
bridged = MOIB.full_bridge_optimizer(MadNLP.Optimizer(print_level=MadNLP.ERROR),Float64)
exclude = ["delete_variable", # Deleting not supported.
"delete_variables", # Deleting not supported.
"getvariable", # Variable names not supported.
"solve_zero_one_with_bounds_1", # Variable names not supported.
"solve_zero_one_with_bounds_2", # Variable names not supported.
"solve_zero_one_with_bounds_3", # Variable names not supported.
"getconstraint", # Constraint names not suported.
"variablenames", # Variable names not supported.
"solve_with_upperbound", # loadfromstring!
"solve_with_lowerbound", # loadfromstring!
"solve_integer_edge_cases", # loadfromstring!
"solve_affine_lessthan", # loadfromstring!
"solve_affine_greaterthan", # loadfromstring!
"solve_affine_equalto", # loadfromstring!
"solve_affine_interval", # loadfromstring!
"get_objective_function", # Function getters not supported.
"solve_constant_obj", # loadfromstring!
"solve_blank_obj", # loadfromstring!
"solve_singlevariable_obj", # loadfromstring!
"solve_objbound_edge_cases", # ObjectiveBound not supported.
"solve_affine_deletion_edge_cases", # Deleting not supported.
"solve_unbounded_model", # `NORM_LIMIT`
"number_threads", # NumberOfThreads not supported
"delete_nonnegative_variables", # get ConstraintFunction n/a.
"update_dimension_nonnegative_variables", # get ConstraintFunction n/a.
"delete_soc_variables", # VectorOfVar. in SOC not supported
"solve_result_index", # DualObjectiveValue not supported
"time_limit_sec", #time limit given as Flaot64?
"solve_farkas_interval_lower",
"solve_farkas_lessthan",
"solve_farkas_interval_upper",
"solve_farkas_greaterthan",
"solve_farkas_variable_lessthan_max",
"solve_farkas_variable_lessthan",
"solve_farkas_equalto_lower",
"solve_farkas_equalto_upper",
"solve_qp_edge_cases"
]
MOIT.unittest(bridged, config, exclude)
# - Excluded because this test is optional
"test_model_ScalarFunctionConstantNotZero",
# - Excluded because MadNLP returns INVALID_MODEL instead of LOCALLY_SOLVED
"test_linear_VectorAffineFunction_empty_row",
]
)
return
end

@testset "MOI QP/QCQP tests" begin
optimizer = MadNLP.Optimizer(print_level=MadNLP.ERROR)
qp_optimizer = MOIU.CachingOptimizer(MOIU.Model{Float64}(), optimizer)
MOIT.qptest(qp_optimizer, config)
exclude = ["qcp1", # VectorAffineFunction not supported.
]
MOIT.qcptest(qp_optimizer, config_no_duals, exclude)
end

TestMOIWrapper.runtests()
2 changes: 1 addition & 1 deletion test/runtests.jl
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
using Test, MadNLP, MadNLPTests, MINLPTests
import MathOptInterface
import AmplNLReader: AmplModel
# import AmplNLReader: AmplModel
import SparseArrays: sparse

@testset "MadNLP test" begin
Expand Down