From c2c5a618d9dc8f389f297c5bcb1917c80de1d897 Mon Sep 17 00:00:00 2001 From: odow Date: Wed, 28 Feb 2024 15:41:07 +1300 Subject: [PATCH 1/2] Add _CONSTRAINT_LIMIT_FOR_PRINTING to control printing of many constraints --- src/print.jl | 47 ++++++++++++++++++++++++++++++++++++++++++---- test/test_print.jl | 27 ++++++++++++++++++++++++++ 2 files changed, 70 insertions(+), 4 deletions(-) diff --git a/src/print.jl b/src/print.jl index 66bedbd4a4e..3a303504721 100644 --- a/src/print.jl +++ b/src/print.jl @@ -282,6 +282,24 @@ function show_backend_summary(io::IO, model::GenericModel) return end +""" + const _CONSTRAINT_LIMIT_FOR_PRINTING = Ref{Int}(100) + +A global constant used to control when constraints are omitted when printing +the model. + +Get and set this value using `_CONSTRAINT_LIMIT_FOR_PRINTING[]`. + +```julia +julia> _CONSTRAINT_LIMIT_FOR_PRINTING[] +100 + +julia> _CONSTRAINT_LIMIT_FOR_PRINTING[] = 10 +10 +``` +""" +const _CONSTRAINT_LIMIT_FOR_PRINTING = Ref{Int}(100) + """ _print_model(io::IO, model::AbstractModel) @@ -303,8 +321,18 @@ function _print_model(io::IO, model::AbstractModel) println(io, "Feasibility") end println(io, "Subject to") - for constraint in constraints_string(mode, model) - println(io, " ", replace(constraint, '\n' => "\n ")) + constraints = constraints_string(mode, model) + m = div(_CONSTRAINT_LIMIT_FOR_PRINTING[], 2) + skip_start = _CONSTRAINT_LIMIT_FOR_PRINTING[] - m + 1 + skip_stop = length(constraints) - m + n = skip_stop - skip_start + 1 + for (i, constraint) in enumerate(constraints) + if i < skip_start || skip_stop < i + println(io, " ", replace(constraint, '\n' => "\n ")) + end + if n > 0 && i == skip_start + println(io, "[[...$n constraints skipped...]]") + end end nl_subexpressions = _nl_subexpression_string(mode, model) if !isempty(nl_subexpressions) @@ -342,8 +370,19 @@ function _print_latex(io::IO, model::AbstractModel) constraints = constraints_string(mode, model) if !isempty(constraints) print(io, "\\text{Subject to} \\quad") - for constraint in constraints - println(io, " & ", constraint, "\\\\") + m = div(_CONSTRAINT_LIMIT_FOR_PRINTING[], 2) + skip_start, skip_stop = m + 1, length(constraints) - m + n = skip_stop - skip_start + for (i, constraint) in enumerate(constraints) + if i <= skip_start || skip_stop <= i + println(io, " & ", constraint, "\\\\") + end + if n > 0 && i == skip_start + println( + io, + " & [[\\ldots\\text{$n constraints skipped}\\ldots]] \\\\", + ) + end end end nl_subexpressions = _nl_subexpression_string(mode, model) diff --git a/test/test_print.jl b/test/test_print.jl index 2eb4945e756..1bf5708c308 100644 --- a/test/test_print.jl +++ b/test/test_print.jl @@ -987,4 +987,31 @@ function test_truncated_printing() return end +function test_skipping_constraints() + model = Model() + @variable(model, 0 <= x[1:100] <= 10, Int) + N = num_constraints(model; count_variable_in_set_constraints = true) + @test N == 300 + str = sprint(print, model) + for i in 1:100 + @test occursin(sprint(print, LowerBoundRef(x[i])), str) == (i <= 50) + end + @test occursin("[[...200 constraints skipped...]]", str) + for i in 1:100 + @test occursin(sprint(print, IntegerRef(x[i])), str) == (i >= 51) + end + ret = JuMP._CONSTRAINT_LIMIT_FOR_PRINTING[] + JuMP._CONSTRAINT_LIMIT_FOR_PRINTING[] = 3 + str = sprint(print, model) + for i in 1:100 + @test occursin(sprint(print, LowerBoundRef(x[i])), str) == (i <= 2) + end + @test occursin("[[...297 constraints skipped...]]", str) + for i in 1:100 + @test occursin(sprint(print, IntegerRef(x[i])), str) == (i >= 100) + end + JuMP._CONSTRAINT_LIMIT_FOR_PRINTING[] = ret + return end + +end # TestPrint From 675c444c2510d16360584a13b25f76defb389db9 Mon Sep 17 00:00:00 2001 From: odow Date: Wed, 28 Feb 2024 15:51:30 +1300 Subject: [PATCH 2/2] Add test for LaTeX --- src/print.jl | 7 ++++--- test/test_print.jl | 47 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 51 insertions(+), 3 deletions(-) diff --git a/src/print.jl b/src/print.jl index 3a303504721..6cf8beb4031 100644 --- a/src/print.jl +++ b/src/print.jl @@ -371,10 +371,11 @@ function _print_latex(io::IO, model::AbstractModel) if !isempty(constraints) print(io, "\\text{Subject to} \\quad") m = div(_CONSTRAINT_LIMIT_FOR_PRINTING[], 2) - skip_start, skip_stop = m + 1, length(constraints) - m - n = skip_stop - skip_start + skip_start = _CONSTRAINT_LIMIT_FOR_PRINTING[] - m + 1 + skip_stop = length(constraints) - m + n = skip_stop - skip_start + 1 for (i, constraint) in enumerate(constraints) - if i <= skip_start || skip_stop <= i + if i < skip_start || skip_stop < i println(io, " & ", constraint, "\\\\") end if n > 0 && i == skip_start diff --git a/test/test_print.jl b/test/test_print.jl index 1bf5708c308..61c553c4ce2 100644 --- a/test/test_print.jl +++ b/test/test_print.jl @@ -1014,4 +1014,51 @@ function test_skipping_constraints() return end +function test_skipping_constraints_latex() + model = Model() + @variable(model, 0 <= x[1:100] <= 10, Int) + N = num_constraints(model; count_variable_in_set_constraints = true) + @test N == 300 + str = sprint(print, latex_formulation(model)) + for i in 1:100 + output = constraint_string( + MIME("text/latex"), + LowerBoundRef(x[i]); + in_math_mode = true, + ) + @test occursin(output, str) == (i <= 50) + end + @test occursin("[[\\ldots\\text{200 constraints skipped}\\ldots]]", str) + for i in 1:100 + output = constraint_string( + MIME("text/latex"), + IntegerRef(x[i]); + in_math_mode = true, + ) + @test occursin(output, str) == (i >= 51) + end + ret = JuMP._CONSTRAINT_LIMIT_FOR_PRINTING[] + JuMP._CONSTRAINT_LIMIT_FOR_PRINTING[] = 3 + str = sprint(print, latex_formulation(model)) + for i in 1:100 + output = constraint_string( + MIME("text/latex"), + LowerBoundRef(x[i]); + in_math_mode = true, + ) + @test occursin(output, str) == (i <= 2) + end + @test occursin("[[\\ldots\\text{297 constraints skipped}\\ldots]]", str) + for i in 1:100 + output = constraint_string( + MIME("text/latex"), + IntegerRef(x[i]); + in_math_mode = true, + ) + @test occursin(output, str) == (i >= 100) + end + JuMP._CONSTRAINT_LIMIT_FOR_PRINTING[] = ret + return +end + end # TestPrint