diff --git a/docs/src/developers/extensions.md b/docs/src/developers/extensions.md index 378bc3d6150..da5a960ef56 100644 --- a/docs/src/developers/extensions.md +++ b/docs/src/developers/extensions.md @@ -364,11 +364,11 @@ MyModel (generic function with 1 method) julia> model = MyModel() A JuMP Model -Feasibility problem with: -Variables: 0 -Model mode: AUTOMATIC -CachingOptimizer state: NO_OPTIMIZER -Solver name: No optimizer attached. +├ solver: none +├ objective_sense: FEASIBILITY_SENSE +├ num_variables: 0 +├ num_constraints: 0 +└ Names registered in the model: none julia> model.ext Dict{Symbol, Any} with 1 entry: diff --git a/docs/src/manual/constraints.md b/docs/src/manual/constraints.md index b2db37737af..bae5b3e7501 100644 --- a/docs/src/manual/constraints.md +++ b/docs/src/manual/constraints.md @@ -351,11 +351,11 @@ corresponding symbol. Get a registered name using `model[:key]`: ```jldoctest julia> model = Model() A JuMP Model -Feasibility problem with: -Variables: 0 -Model mode: AUTOMATIC -CachingOptimizer state: NO_OPTIMIZER -Solver name: No optimizer attached. +├ solver: none +├ objective_sense: FEASIBILITY_SENSE +├ num_variables: 0 +├ num_constraints: 0 +└ Names registered in the model: none julia> @variable(model, x) x @@ -365,13 +365,13 @@ my_c : 2 x ≤ 1 julia> model A JuMP Model -Feasibility problem with: -Variable: 1 -`AffExpr`-in-`MathOptInterface.LessThan{Float64}`: 1 constraint -Model mode: AUTOMATIC -CachingOptimizer state: NO_OPTIMIZER -Solver name: No optimizer attached. -Names registered in the model: my_c, x +├ solver: none +├ objective_sense: FEASIBILITY_SENSE +├ num_variables: 1 +├ num_constraints: 1 +│ └ AffExpr in MOI.LessThan{Float64}: 1 +└ Names registered in the model + └ :my_c, :x julia> model[:my_c] === my_c true @@ -567,13 +567,13 @@ c : 2 x ≤ 1 julia> model A JuMP Model -Feasibility problem with: -Variable: 1 -`AffExpr`-in-`MathOptInterface.LessThan{Float64}`: 1 constraint -Model mode: AUTOMATIC -CachingOptimizer state: NO_OPTIMIZER -Solver name: No optimizer attached. -Names registered in the model: x +├ solver: none +├ objective_sense: FEASIBILITY_SENSE +├ num_variables: 1 +├ num_constraints: 1 +│ └ AffExpr in MOI.LessThan{Float64}: 1 +└ Names registered in the model + └ :x julia> c ERROR: UndefVarError: `c` not defined @@ -589,13 +589,13 @@ c : 2 x ≤ 1 julia> model A JuMP Model -Feasibility problem with: -Variable: 1 -`AffExpr`-in-`MathOptInterface.LessThan{Float64}`: 1 constraint -Model mode: AUTOMATIC -CachingOptimizer state: NO_OPTIMIZER -Solver name: No optimizer attached. -Names registered in the model: c_register, x +├ solver: none +├ objective_sense: FEASIBILITY_SENSE +├ num_variables: 1 +├ num_constraints: 1 +│ └ AffExpr in MOI.LessThan{Float64}: 1 +└ Names registered in the model + └ :c_register, :x julia> model[:c_register] c : 2 x ≤ 1 @@ -1597,13 +1597,14 @@ x[1] && x[2] = false julia> model A JuMP Model -Feasibility problem with: -Variables: 2 -`GenericNonlinearExpr{GenericVariableRef{Bool}}`-in-`MathOptInterface.EqualTo{Bool}`: 2 constraints -Model mode: AUTOMATIC -CachingOptimizer state: NO_OPTIMIZER -Solver name: No optimizer attached. -Names registered in the model: x +├ value_type: Bool +├ solver: none +├ objective_sense: FEASIBILITY_SENSE +├ num_variables: 2 +├ num_constraints: 2 +│ └ GenericNonlinearExpr{GenericVariableRef{Bool}} in MOI.EqualTo{Bool}: 2 +└ Names registered in the model + └ :x ``` Boolean constraints should not be added using the `==` operator because JuMP diff --git a/docs/src/manual/models.md b/docs/src/manual/models.md index 8ad0837ea26..d63f97ddbd7 100644 --- a/docs/src/manual/models.md +++ b/docs/src/manual/models.md @@ -27,11 +27,11 @@ Create a model by passing an optimizer to [`Model`](@ref): ```jldoctest julia> model = Model(HiGHS.Optimizer) A JuMP Model -Feasibility problem with: -Variables: 0 -Model mode: AUTOMATIC -CachingOptimizer state: EMPTY_OPTIMIZER -Solver name: HiGHS +├ solver: HiGHS +├ objective_sense: FEASIBILITY_SENSE +├ num_variables: 0 +├ num_constraints: 0 +└ Names registered in the model: none ``` If you don't know which optimizer you will be using at creation time, create a @@ -40,11 +40,11 @@ prior to [`optimize!`](@ref): ```jldoctest julia> model = Model() A JuMP Model -Feasibility problem with: -Variables: 0 -Model mode: AUTOMATIC -CachingOptimizer state: NO_OPTIMIZER -Solver name: No optimizer attached. +├ solver: none +├ objective_sense: FEASIBILITY_SENSE +├ num_variables: 0 +├ num_constraints: 0 +└ Names registered in the model: none julia> set_optimizer(model, HiGHS.Optimizer) ``` @@ -127,11 +127,11 @@ julia> import MultiObjectiveAlgorithms as MOA julia> model = Model(() -> MOA.Optimizer(HiGHS.Optimizer)) A JuMP Model -Feasibility problem with: -Variables: 0 -Model mode: AUTOMATIC -CachingOptimizer state: EMPTY_OPTIMIZER -Solver name: MOA[algorithm=MultiObjectiveAlgorithms.Lexicographic, optimizer=HiGHS] +├ solver: MOA[algorithm=MultiObjectiveAlgorithms.Lexicographic, optimizer=HiGHS] +├ objective_sense: FEASIBILITY_SENSE +├ num_variables: 0 +├ num_constraints: 0 +└ Names registered in the model: none ``` ## [Solver options](@id solver_options) @@ -144,11 +144,11 @@ julia> model = Model( optimizer_with_attributes(HiGHS.Optimizer, "output_flag" => false), ) A JuMP Model -Feasibility problem with: -Variables: 0 -Model mode: AUTOMATIC -CachingOptimizer state: EMPTY_OPTIMIZER -Solver name: HiGHS +├ solver: HiGHS +├ objective_sense: FEASIBILITY_SENSE +├ num_variables: 0 +├ num_constraints: 0 +└ Names registered in the model: none ``` Alternatively, use [`set_attribute`](@ref) to set an attribute after @@ -214,14 +214,14 @@ julia> model = Model(); @variable(model, x >= 0); @objective(model, Max, x); julia> model A JuMP Model -Maximization problem with: -Variable: 1 -Objective function type: VariableRef -`VariableRef`-in-`MathOptInterface.GreaterThan{Float64}`: 1 constraint -Model mode: AUTOMATIC -CachingOptimizer state: NO_OPTIMIZER -Solver name: No optimizer attached. -Names registered in the model: x +├ solver: none +├ objective_sense: MAX_SENSE +│ └ objective_function_type: VariableRef +├ num_variables: 1 +├ num_constraints: 1 +│ └ VariableRef in MOI.GreaterThan{Float64}: 1 +└ Names registered in the model + └ :x ``` Use `print` to print the formulation of the model (in IJulia, this will render @@ -356,23 +356,23 @@ JuMP models can be created from file formats using [`read_from_file`](@ref) and ```jldoctest file_formats julia> model = read_from_file("model.mps") A JuMP Model -Minimization problem with: -Variables: 0 -Objective function type: AffExpr -Model mode: AUTOMATIC -CachingOptimizer state: NO_OPTIMIZER -Solver name: No optimizer attached. +├ solver: none +├ objective_sense: MIN_SENSE +│ └ objective_function_type: AffExpr +├ num_variables: 0 +├ num_constraints: 0 +└ Names registered in the model: none julia> seekstart(io); julia> model2 = read(io, Model; format = MOI.FileFormats.FORMAT_MPS) A JuMP Model -Minimization problem with: -Variables: 0 -Objective function type: AffExpr -Model mode: AUTOMATIC -CachingOptimizer state: NO_OPTIMIZER -Solver name: No optimizer attached. +├ solver: none +├ objective_sense: MIN_SENSE +│ └ objective_function_type: AffExpr +├ num_variables: 0 +├ num_constraints: 0 +└ Names registered in the model: none ``` !!! note @@ -634,11 +634,11 @@ Use the `add_bridges = false` keyword to remove the bridging layer: ```jldoctest julia> model = Model(HiGHS.Optimizer; add_bridges = false) A JuMP Model -Feasibility problem with: -Variables: 0 -Model mode: AUTOMATIC -CachingOptimizer state: EMPTY_OPTIMIZER -Solver name: HiGHS +├ solver: HiGHS +├ objective_sense: FEASIBILITY_SENSE +├ num_variables: 0 +├ num_constraints: 0 +└ Names registered in the model: none julia> backend(model) MOIU.CachingOptimizer @@ -694,10 +694,12 @@ JuMP model using [`direct_model`](@ref): ```jldoctest direct_mode julia> model = direct_model(HiGHS.Optimizer()) A JuMP Model -Feasibility problem with: -Variables: 0 -Model mode: DIRECT -Solver name: HiGHS +├ mode: DIRECT +├ solver: HiGHS +├ objective_sense: FEASIBILITY_SENSE +├ num_variables: 0 +├ num_constraints: 0 +└ Names registered in the model: none ``` !!! warning diff --git a/docs/src/manual/solutions.md b/docs/src/manual/solutions.md index 99d83b4d164..d3f1a53d071 100644 --- a/docs/src/manual/solutions.md +++ b/docs/src/manual/solutions.md @@ -608,13 +608,7 @@ julia> using JuMP julia> import Gurobi -julia> model = Model(Gurobi.Optimizer) -A JuMP Model -Feasibility problem with: -Variables: 0 -Model mode: AUTOMATIC -CachingOptimizer state: EMPTY_OPTIMIZER -Solver name: Gurobi +julia> model = Model(Gurobi.Optimizer); julia> set_silent(model) diff --git a/docs/src/manual/variables.md b/docs/src/manual/variables.md index dc3b33c0c39..9c488ad4d0e 100644 --- a/docs/src/manual/variables.md +++ b/docs/src/manual/variables.md @@ -190,23 +190,23 @@ corresponding symbol. Get a registered name using `model[:key]`: ```jldoctest julia> model = Model() A JuMP Model -Feasibility problem with: -Variables: 0 -Model mode: AUTOMATIC -CachingOptimizer state: NO_OPTIMIZER -Solver name: No optimizer attached. +├ solver: none +├ objective_sense: FEASIBILITY_SENSE +├ num_variables: 0 +├ num_constraints: 0 +└ Names registered in the model: none julia> @variable(model, x) x julia> model A JuMP Model -Feasibility problem with: -Variable: 1 -Model mode: AUTOMATIC -CachingOptimizer state: NO_OPTIMIZER -Solver name: No optimizer attached. -Names registered in the model: x +├ solver: none +├ objective_sense: FEASIBILITY_SENSE +├ num_variables: 1 +├ num_constraints: 0 +└ Names registered in the model + └ :x julia> model[:x] === x true @@ -430,11 +430,11 @@ x julia> model A JuMP Model -Feasibility problem with: -Variable: 1 -Model mode: AUTOMATIC -CachingOptimizer state: NO_OPTIMIZER -Solver name: No optimizer attached. +├ solver: none +├ objective_sense: FEASIBILITY_SENSE +├ num_variables: 1 +├ num_constraints: 0 +└ Names registered in the model: none julia> x ERROR: UndefVarError: `x` not defined @@ -450,12 +450,12 @@ x julia> model A JuMP Model -Feasibility problem with: -Variable: 1 -Model mode: AUTOMATIC -CachingOptimizer state: NO_OPTIMIZER -Solver name: No optimizer attached. -Names registered in the model: x_register +├ solver: none +├ objective_sense: FEASIBILITY_SENSE +├ num_variables: 1 +├ num_constraints: 0 +└ Names registered in the model + └ :x_register julia> model[:x_register] x diff --git a/src/JuMP.jl b/src/JuMP.jl index e2bf709bbc1..11589b51419 100644 --- a/src/JuMP.jl +++ b/src/JuMP.jl @@ -266,10 +266,12 @@ julia> optimizer = optimizer_with_attributes( julia> model = direct_generic_model(Float64, optimizer) A JuMP Model -Feasibility problem with: -Variables: 0 -Model mode: DIRECT -Solver name: HiGHS +├ mode: DIRECT +├ solver: HiGHS +├ objective_sense: FEASIBILITY_SENSE +├ num_variables: 0 +├ num_constraints: 0 +└ Names registered in the model: none ``` is equivalent to: ```jldoctest @@ -277,10 +279,12 @@ julia> import HiGHS julia> model = direct_generic_model(Float64, HiGHS.Optimizer()) A JuMP Model -Feasibility problem with: -Variables: 0 -Model mode: DIRECT -Solver name: HiGHS +├ mode: DIRECT +├ solver: HiGHS +├ objective_sense: FEASIBILITY_SENSE +├ num_variables: 0 +├ num_constraints: 0 +└ Names registered in the model: none julia> set_attribute(model, "presolve", "off") @@ -371,10 +375,12 @@ julia> optimizer = optimizer_with_attributes( julia> model = direct_model(optimizer) A JuMP Model -Feasibility problem with: -Variables: 0 -Model mode: DIRECT -Solver name: HiGHS +├ mode: DIRECT +├ solver: HiGHS +├ objective_sense: FEASIBILITY_SENSE +├ num_variables: 0 +├ num_constraints: 0 +└ Names registered in the model: none ``` is equivalent to: ```jldoctest @@ -382,10 +388,12 @@ julia> import HiGHS julia> model = direct_model(HiGHS.Optimizer()) A JuMP Model -Feasibility problem with: -Variables: 0 -Model mode: DIRECT -Solver name: HiGHS +├ mode: DIRECT +├ solver: HiGHS +├ objective_sense: FEASIBILITY_SENSE +├ num_variables: 0 +├ num_constraints: 0 +└ Names registered in the model: none julia> set_attribute(model, "presolve", "off") @@ -485,11 +493,11 @@ julia> import HiGHS julia> model = Model(HiGHS.Optimizer) A JuMP Model -Feasibility problem with: -Variables: 0 -Model mode: AUTOMATIC -CachingOptimizer state: EMPTY_OPTIMIZER -Solver name: HiGHS +├ solver: HiGHS +├ objective_sense: FEASIBILITY_SENSE +├ num_variables: 0 +├ num_constraints: 0 +└ Names registered in the model: none julia> MOI.Utilities.attach_optimizer(model) @@ -907,11 +915,11 @@ false julia> empty!(model) A JuMP Model -Feasibility problem with: -Variables: 0 -Model mode: AUTOMATIC -CachingOptimizer state: NO_OPTIMIZER -Solver name: No optimizer attached. +├ solver: none +├ objective_sense: FEASIBILITY_SENSE +├ num_variables: 0 +├ num_constraints: 0 +└ Names registered in the model: none julia> print(model) Feasibility diff --git a/src/print.jl b/src/print.jl index aa088d9198d..dcad0e57a50 100644 --- a/src/print.jl +++ b/src/print.jl @@ -234,6 +234,62 @@ function _print_summary(io::IO, model::AbstractModel) return end +function _print_summary(io::IO, model::GenericModel{T}) where {T} + println(io, name(model)) + if T != Float64 + println(io, "├ value_type: ", T) + end + if mode(model) != AUTOMATIC + println(io, "├ mode: ", mode(model)) + end + println(io, "├ solver: ", _try_solver_name(model)) + sense = objective_sense(model) + println(io, "├ objective_sense: ", sense) + if sense != FEASIBILITY_SENSE + F = objective_function_type(model) + println(io, "│ └ objective_function_type: ", F) + end + println(io, "├ num_variables: ", num_variables(model)) + n_constraints = 0 + constraint_lines = String[] + for (F, S) in list_of_constraint_types(model) + n = num_constraints(model, F, S) + n_constraints += n + line = sprint(MOI.Utilities.print_with_acronym, "$F in $S: $n") + push!(constraint_lines, line) + end + n = num_nonlinear_constraints(model) + if n > 0 + n_constraints += n + push!(constraint_lines, "Nonlinear: $n") + end + println(io, "├ num_constraints: $n_constraints") + for (i, line) in enumerate(constraint_lines) + tag = i == length(constraint_lines) ? "└" : "├" + println(io, "│ $tag $line") + end + print(io, "└ Names registered in the model") + if isempty(object_dictionary(model)) + print(io, ": none") + else + names = sort!(collect(keys(object_dictionary(model)))) + print(io, "\n └ :", join(names, ", :")) + end + return +end + +function _try_solver_name(model) + if mode(model) != DIRECT && + MOI.Utilities.state(backend(model)) == MOI.Utilities.NO_OPTIMIZER + return "none" + end + try + return MOI.get(backend(model), MOI.SolverName()) + catch + return "unknown" + end +end + """ show_objective_function_summary(io::IO, model::AbstractModel) diff --git a/test/test_print.jl b/test/test_print.jl index 66d0ff34fe0..7682fdfb6db 100644 --- a/test/test_print.jl +++ b/test/test_print.jl @@ -636,24 +636,24 @@ Subject to MIME("text/plain"), model_1, """ -A JuMP Model -Maximization problem with: -Variables: 13 -Objective function type: $(GenericAffExpr{Float64,VariableType}) -`$(GenericAffExpr{Float64,VariableType})`-in-`MathOptInterface.LessThan{Float64}`: 1 constraint -`$(GenericQuadExpr{Float64,VariableType})`-in-`MathOptInterface.LessThan{Float64}`: 1 constraint -`$(Array{VariableType,1})`-in-`MathOptInterface.PositiveSemidefiniteConeTriangle`: 2 constraints -`$(Array{VariableType,1})`-in-`MathOptInterface.PositiveSemidefiniteConeSquare`: 2 constraints -`$(Array{GenericAffExpr{Float64,VariableType},1})`-in-`MathOptInterface.SecondOrderCone`: 1 constraint -`$VariableType`-in-`MathOptInterface.EqualTo{Float64}`: 1 constraint -`$VariableType`-in-`MathOptInterface.GreaterThan{Float64}`: 4 constraints -`$VariableType`-in-`MathOptInterface.LessThan{Float64}`: 4 constraints -`$VariableType`-in-`MathOptInterface.Integer`: 4 constraints -`$VariableType`-in-`MathOptInterface.ZeroOne`: 4 constraints -Model mode: AUTOMATIC -CachingOptimizer state: NO_OPTIMIZER -Solver name: No optimizer attached. -Names registered in the model: a, a1, b, b1, c, c1, con, fi, soc, u, x, y, z"""; + A JuMP Model + ├ solver: none + ├ objective_sense: MAX_SENSE + │ └ objective_function_type: $(GenericAffExpr{Float64,VariableType}) + ├ num_variables: 13 + ├ num_constraints: 24 + │ ├ $(GenericAffExpr{Float64,VariableType}) in MOI.LessThan{Float64}: 1 + │ ├ $(GenericQuadExpr{Float64,VariableType}) in MOI.LessThan{Float64}: 1 + │ ├ $(Vector{VariableType}) in MOI.PositiveSemidefiniteConeTriangle: 2 + │ ├ $(Vector{VariableType}) in MOI.PositiveSemidefiniteConeSquare: 2 + │ ├ $(Vector{GenericAffExpr{Float64,VariableType}}) in MOI.SecondOrderCone: 1 + │ ├ $VariableType in MOI.EqualTo{Float64}: 1 + │ ├ $VariableType in MOI.GreaterThan{Float64}: 4 + │ ├ $VariableType in MOI.LessThan{Float64}: 4 + │ ├ $VariableType in MOI.Integer: 4 + │ └ $VariableType in MOI.ZeroOne: 4 + └ Names registered in the model + └ :a, :a1, :b, :b1, :c, :c1, :con, :fi, :soc, :u, :x, :y, :z"""; repl = :show, ) @@ -706,16 +706,16 @@ Names registered in the model: a, a1, b, b1, c, c1, con, fi, soc, u, x, y, z"""; MIME("text/plain"), model_2, """ -A JuMP Model -Feasibility problem with: -Variables: 2 -`$(GenericQuadExpr{Float64,VariableType})`-in-`MathOptInterface.LessThan{Float64}`: 1 constraint -`$VariableType`-in-`MathOptInterface.Integer`: 1 constraint -`$VariableType`-in-`MathOptInterface.ZeroOne`: 1 constraint -Model mode: AUTOMATIC -CachingOptimizer state: NO_OPTIMIZER -Solver name: No optimizer attached. -Names registered in the model: x, y"""; + A JuMP Model + ├ solver: none + ├ objective_sense: FEASIBILITY_SENSE + ├ num_variables: 2 + ├ num_constraints: 3 + │ ├ $(GenericQuadExpr{Float64,VariableType}) in MOI.LessThan{Float64}: 1 + │ ├ $VariableType in MOI.Integer: 1 + │ └ $VariableType in MOI.ZeroOne: 1 + └ Names registered in the model + └ :x, :y"""; repl = :show, ) @@ -727,14 +727,14 @@ Names registered in the model: x, y"""; MIME("text/plain"), model_3, """ -A JuMP Model -Feasibility problem with: -Variable: 1 -`$(GenericAffExpr{Float64,VariableType})`-in-`MathOptInterface.LessThan{Float64}`: 1 constraint -Model mode: AUTOMATIC -CachingOptimizer state: NO_OPTIMIZER -Solver name: No optimizer attached. -Names registered in the model: x"""; + A JuMP Model + ├ solver: none + ├ objective_sense: FEASIBILITY_SENSE + ├ num_variables: 1 + ├ num_constraints: 1 + │ └ $(GenericAffExpr{Float64,VariableType}) in MOI.LessThan{Float64}: 1 + └ Names registered in the model + └ :x"""; repl = :show, ) return @@ -752,15 +752,15 @@ function test_printing_model_with_nonlinear() MIME("text/plain"), model, """ -A JuMP Model -Maximization problem with: -Variable: 1 -Objective function type: Nonlinear -Nonlinear: 1 constraint -Model mode: AUTOMATIC -CachingOptimizer state: NO_OPTIMIZER -Solver name: No optimizer attached. -Names registered in the model: x"""; + A JuMP Model + ├ solver: none + ├ objective_sense: MAX_SENSE + │ └ objective_function_type: $AffExpr + ├ num_variables: 1 + ├ num_constraints: 1 + │ └ Nonlinear: 1 + └ Names registered in the model + └ :x"""; repl = :show, ) @@ -849,7 +849,7 @@ function test_print_summary_min_sense() model = Model() @variable(model, x) @objective(model, Min, x) - @test occursin("Minimization problem with:", sprint(show, model)) + @test occursin("objective_sense: MIN_SENSE", sprint(show, model)) end function test_show_latex_parameter() @@ -1110,4 +1110,18 @@ function test_symmetric_constraint() return end +function test_show_generic_model_bigfloat() + model = GenericModel{BigFloat}() + ret = """ + A JuMP Model + ├ value_type: BigFloat + ├ solver: none + ├ objective_sense: FEASIBILITY_SENSE + ├ num_variables: 0 + ├ num_constraints: 0 + └ Names registered in the model: none""" + @test sprint(show, model) == ret + return +end + end # TestPrint