From dfad9ca8c246414c76e970c1a4e28bad221c0c65 Mon Sep 17 00:00:00 2001 From: Oscar Dowson Date: Mon, 19 Oct 2026 17:41:47 +1300 Subject: [PATCH] [FileFormats.MPS] throw an error when the function constant is not zero --- src/FileFormats/MPS/write.jl | 6 ++++ test/FileFormats/MPS/test_MPS.jl | 58 ++++++++++++++++++++++++++++---- 2 files changed, 58 insertions(+), 6 deletions(-) diff --git a/src/FileFormats/MPS/write.jl b/src/FileFormats/MPS/write.jl index fc37bac531..d2de1a5470 100644 --- a/src/FileFormats/MPS/write.jl +++ b/src/FileFormats/MPS/write.jl @@ -260,6 +260,9 @@ function _collect_coefficients( for index in MOI.get(model, MOI.ListOfConstraintIndices{F,S}()) row_name = MOI.get(model, MOI.ConstraintName(), index) func = MOI.get(model, MOI.ConstraintFunction(), index) + if !iszero(func.constant) + throw(MOI.ScalarFunctionConstantNotZero{T,F,S}(func.constant)) + end _extract_terms(var_to_column, coefficients, row_name, func) end return @@ -281,6 +284,9 @@ function _collect_indicator( func = MOI.get(model, MOI.ConstraintFunction(), index) funcs = MOI.Utilities.eachscalar(func) z = convert(MOI.VariableIndex, funcs[1]) + if !iszero(func.constants[2]) + throw(MOI.ScalarFunctionConstantNotZero{T,F,S}(func.constants[2])) + end _extract_terms(var_to_column, coefficients, row_name, funcs[2]) condition = _activation_condition(S) var_name = _var_name(model, z, var_to_column[z], options.generic_names) diff --git a/test/FileFormats/MPS/test_MPS.jl b/test/FileFormats/MPS/test_MPS.jl index 44e88b318f..6203ffca19 100644 --- a/test/FileFormats/MPS/test_MPS.jl +++ b/test/FileFormats/MPS/test_MPS.jl @@ -13,12 +13,9 @@ import MathOptInterface.FileFormats: MPS import OrderedCollections: OrderedDict function runtests() - for name in names(@__MODULE__; all = true) - if startswith("$(name)", "test_") - @testset "$name" begin - getfield(@__MODULE__, name)() - end - end + is_test(name) = startswith("$name", "test_") + @testset "$name" for name in filter(is_test, names(@__MODULE__; all = true)) + getfield(@__MODULE__, name)() end return end @@ -1926,6 +1923,55 @@ function test_semi_reading_2() return end +function test_scalar_function_constant_not_zero() + for input in [ + """ + variables: x + c: 1.0 * x + 2.0 >= 3.0 + """, + """ + variables: x + c: 1.0 * x * x + 2.0 >= 3.0 + """, + """ + variables: x + c: 1.0 * x + 2.0 <= 3.0 + """, + """ + variables: x + c: 1.0 * x * x + 2.0 <= 3.0 + """, + """ + variables: x + c: 1.0 * x + 2.0 == 3.0 + """, + """ + variables: x + c: 1.0 * x * x + 2.0 == 3.0 + """, + """ + variables: x, z + c: [z, 1.0 * x + 2.0] in Indicator{ACTIVATE_ON_ONE}(LessThan(1.0)) + z in ZeroOne() + """, + """ + variables: x, z + c: [z, 1.0 * x + 2.0] in Indicator{ACTIVATE_ON_ONE}(GreaterThan(1.0)) + z in ZeroOne() + """, + """ + variables: x, z + c: [z, 1.0 * x + 2.0] in Indicator{ACTIVATE_ON_ONE}(EqualTo(1.0)) + z in ZeroOne() + """, + ] + model = MPS.Model() + MOI.Utilities.loadfromstring!(model, input) + @test_throws(MOI.ScalarFunctionConstantNotZero, sprint(write, model)) + end + return +end + end # TestMPS TestMPS.runtests()