From d245dcf5de227d866f4de4b3a726fd6e09e0ad84 Mon Sep 17 00:00:00 2001 From: odow Date: Thu, 7 Sep 2023 10:06:26 +1200 Subject: [PATCH 1/3] [FileFormats.MOF] add support for Scaled set --- src/FileFormats/MOF/MOF.jl | 7 +++--- ...of.1.4.schema.json => mof.1.5.schema.json} | 19 ++++++++++++---- src/FileFormats/MOF/read.jl | 5 +++++ src/FileFormats/MOF/write.jl | 6 ++--- test/FileFormats/MOF/MOF.jl | 22 +++++++++++++++++++ 5 files changed, 49 insertions(+), 10 deletions(-) rename src/FileFormats/MOF/{mof.1.4.schema.json => mof.1.5.schema.json} (98%) diff --git a/src/FileFormats/MOF/MOF.jl b/src/FileFormats/MOF/MOF.jl index 5d050721fd..b176ca6675 100644 --- a/src/FileFormats/MOF/MOF.jl +++ b/src/FileFormats/MOF/MOF.jl @@ -11,10 +11,10 @@ import OrderedCollections import JSON import MathOptInterface as MOI -const SCHEMA_PATH = joinpath(@__DIR__, "mof.1.4.schema.json") -const VERSION = v"1.4" +const SCHEMA_PATH = joinpath(@__DIR__, "mof.1.5.schema.json") +const VERSION = v"1.5" const SUPPORTED_VERSIONS = - (v"1.4", v"1.3", v"1.2", v"1.1", v"1.0", v"0.6", v"0.5", v"0.4") + (v"1.5", v"1.4", v"1.3", v"1.2", v"1.1", v"1.0", v"0.6", v"0.5", v"0.4") const OrderedObject = OrderedCollections.OrderedDict{String,Any} const UnorderedObject = Dict{String,Any} @@ -92,6 +92,7 @@ MOI.Utilities.@model( # Indicator is handled by UniversalFallback. # Reified is handled by UniversalFallback. +# Scaled is handled bby UniversalFallback. const Model = MOI.Utilities.UniversalFallback{InnerModel{Float64}} diff --git a/src/FileFormats/MOF/mof.1.4.schema.json b/src/FileFormats/MOF/mof.1.5.schema.json similarity index 98% rename from src/FileFormats/MOF/mof.1.4.schema.json rename to src/FileFormats/MOF/mof.1.5.schema.json index 4adcf4b1ae..96f7e22897 100644 --- a/src/FileFormats/MOF/mof.1.4.schema.json +++ b/src/FileFormats/MOF/mof.1.5.schema.json @@ -1,6 +1,6 @@ { "$schema": "https://json-schema.org/schema#", - "$id": "https://jump.dev/MathOptFormat/schemas/mof.1.4.schema.json", + "$id": "https://jump.dev/MathOptFormat/schemas/mof.1.5.schema.json", "title": "The schema for MathOptFormat", "type": "object", "required": ["version", "variables", "objective", "constraints"], @@ -11,7 +11,7 @@ "required": ["minor", "major"], "properties": { "minor": { - "enum": [0, 1, 2, 3, 4] + "enum": [0, 1, 2, 3, 4, 5] }, "major": { "const": 1 @@ -765,8 +765,7 @@ } } }, { - "description": "The (vectorized) cone of symmetric positive semidefinite matrices, with `side_dimension` rows and columns, such that the off-diagonal entries are scaled by √2. The entries of the upper-right triangular part of the matrix are given column by column (or equivalently, the entries of the lower-left triangular part are given row by row).", - "examples": ["{\"type\": \"ScaledPositiveSemidefiniteConeTriangle\", \"side_dimension\": 2}"], + "description": "DEPRECATED: use the Scaled set combinned with PositiveSemidefiniteConeTriangle instead.", "required": ["side_dimension"], "properties": { "type": { @@ -1151,6 +1150,18 @@ "type": "number" } } + }, { + "description": "The set in the `set` field, scaled such that the inner product of two elements in the set is the same as the dot product of the two vector functions. This is most useful for solvers which require PSD matrices in _scaled_ form.", + "examples": ["{\"type\": \"Scaled\", \"set\": {\"type\": \"PositiveSemidefiniteConeTriangle\", \"side_dimension\": 2}}"], + "required": ["set"], + "properties": { + "type": { + "const": "Scaled" + }, + "set": { + "$ref": "#/definitions/vector_sets" + } + } }] } } diff --git a/src/FileFormats/MOF/read.jl b/src/FileFormats/MOF/read.jl index c5846a5882..368de7959d 100644 --- a/src/FileFormats/MOF/read.jl +++ b/src/FileFormats/MOF/read.jl @@ -383,6 +383,7 @@ end LogDetConeSquare, PositiveSemidefiniteConeTriangle, ScaledPositiveSemidefiniteConeTriangle, # Required for v1.4 + Scaled, # Required for v1.5 PositiveSemidefiniteConeSquare, HermitianPositiveSemidefiniteConeTriangle, ExponentialCone, @@ -543,6 +544,10 @@ function set_to_moi( return MOI.Scaled(MOI.PositiveSemidefiniteConeTriangle(d)) end +function set_to_moi(::Val{:Scaled}, object::Object) + return MOI.Scaled(set_to_moi(object["set"])) +end + function set_to_moi(::Val{:PositiveSemidefiniteConeSquare}, object::Object) return MOI.PositiveSemidefiniteConeSquare(object["side_dimension"]) end diff --git a/src/FileFormats/MOF/write.jl b/src/FileFormats/MOF/write.jl index c2c3344285..222f6762d1 100644 --- a/src/FileFormats/MOF/write.jl +++ b/src/FileFormats/MOF/write.jl @@ -358,11 +358,11 @@ function moi_to_object( end function moi_to_object( - set::MOI.Scaled{MOI.PositiveSemidefiniteConeTriangle}, + set::MOI.Scaled, name_map::Dict{MOI.VariableIndex,String}, ) return OrderedObject( - "type" => "ScaledPositiveSemidefiniteConeTriangle", - "side_dimension" => set.set.side_dimension, + "type" => "Scaled", + "set" => moi_to_object(set.set, name_map), ) end diff --git a/test/FileFormats/MOF/MOF.jl b/test/FileFormats/MOF/MOF.jl index 1fc7ea9cc0..810ccde364 100644 --- a/test/FileFormats/MOF/MOF.jl +++ b/test/FileFormats/MOF/MOF.jl @@ -782,6 +782,18 @@ c1: [x1, x2, x3] in ScaledPositiveSemidefiniteConeTriangle(2) ) end +function test_Scaled_PositiveSemidefiniteConeTriangle() + return _test_model_equality( + """ +variables: x1, x2, x3 +minobjective: x1 +c1: [x1, x2, x3] in Scaled(PositiveSemidefiniteConeTriangle(2)) +""", + ["x1", "x2", "x3"], + ["c1"], + ) +end + function test_PositiveSemidefiniteConeSquare() return _test_model_equality( """ @@ -1364,6 +1376,16 @@ function test_integer_coefficients() return end +function test_ScaledPositiveSemidefiniteConeTriangle() + object = Dict( + "type" => "ScaledPositiveSemidefiniteConeTriangle", + "side_dimension" => 2, + ) + @test MOF.set_to_moi(object) == + MOI.Scaled(MOI.PositiveSemidefiniteConeTriangle(2)) + return +end + end TestMOF.runtests() From 223321f1fa90196e54d8d1420f5d4ab291e3d0ba Mon Sep 17 00:00:00 2001 From: odow Date: Thu, 7 Sep 2023 10:35:44 +1200 Subject: [PATCH 2/3] Fix docs --- docs/src/submodules/FileFormats/overview.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/src/submodules/FileFormats/overview.md b/docs/src/submodules/FileFormats/overview.md index c99f4c5b15..6757f981d0 100644 --- a/docs/src/submodules/FileFormats/overview.md +++ b/docs/src/submodules/FileFormats/overview.md @@ -94,7 +94,7 @@ julia> print(read("file.mof.json", String)) "name": "MathOptFormat Model", "version": { "major": 1, - "minor": 4 + "minor": 5 }, "variables": [ { @@ -230,7 +230,7 @@ julia> good_model = JSON.parse(""" { "version": { "major": 1, - "minor": 4 + "minor": 5 }, "variables": [{"name": "x"}], "objective": {"sense": "feasibility"}, @@ -249,7 +249,7 @@ julia> bad_model = JSON.parse(""" { "version": { "major": 1, - "minor": 4 + "minor": 5 }, "variables": [{"NaMe": "x"}], "objective": {"sense": "feasibility"}, From 9f83170e24d48786fc66983438ac700c7f0271bf Mon Sep 17 00:00:00 2001 From: odow Date: Thu, 7 Sep 2023 10:38:04 +1200 Subject: [PATCH 3/3] Fix test --- test/FileFormats/MOF/nlp.mof.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/FileFormats/MOF/nlp.mof.json b/test/FileFormats/MOF/nlp.mof.json index 188125d845..bdb6e635dc 100644 --- a/test/FileFormats/MOF/nlp.mof.json +++ b/test/FileFormats/MOF/nlp.mof.json @@ -2,7 +2,7 @@ "name": "MathOptFormat Model", "version": { "major": 1, - "minor": 4 + "minor": 5 }, "variables": [ {