From 7d721b0e2f3fa8efe788a2545543e9cec770ff13 Mon Sep 17 00:00:00 2001 From: odow Date: Mon, 20 Jan 2025 08:41:41 +1300 Subject: [PATCH 1/6] [docs] exclude Gurobi examples if built from fork --- docs/make.jl | 49 +++++++++++++++++++++++++++++++++++------------- src/callbacks.jl | 14 ++------------ 2 files changed, 38 insertions(+), 25 deletions(-) diff --git a/docs/make.jl b/docs/make.jl index bd0a29d3fde..0d8a72dbed8 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -6,6 +6,7 @@ import Documenter import DocumenterCitations import Downloads +import Gurobi import Literate import MathOptInterface import Pkg @@ -30,6 +31,23 @@ const _IS_GITHUB_ACTIONS = get(ENV, "GITHUB_ACTIONS", "false") == "true" # Pass --pdf to build the PDF. On GitHub actions, we always build the PDF. const _PDF = findfirst(isequal("--pdf"), ARGS) !== nothing || _IS_GITHUB_ACTIONS +# Exclude these files because they require ${{ secrets.WLSLICENSE }}, which +# is not available to forks. +const _HAS_GUROBI = try + Gurobi.Env() + true +catch + false +end + +const _GUROBI_EXCLUDES = String[] +if !_HAS_GUROBI + push!(_GUROBI_EXCLUDES, "benders_decomposition.jl") + push!(_GUROBI_EXCLUDES, "tsp_lazy_constraints.jl") + push!(_GUROBI_EXCLUDES, "callbacks.jl") + push!(_GUROBI_EXCLUDES, "multiple_solutions.jl") +end + # ============================================================================== # Run literate.jl # ============================================================================== @@ -55,10 +73,13 @@ function _link_example(content) end function _file_list(full_dir, relative_dir, extension) - return map( - file -> joinpath(relative_dir, file), - filter(file -> endswith(file, extension), sort(readdir(full_dir))), - ) + function filter_fn(filename) + return endswith(filename, extension) && + all(f -> _HAS_GUROBI || !endswith(filename, f), _GUROBI_EXCLUDES) + end + return map(filter!(filter_fn, sort!(readdir(full_dir)))) do file + return joinpath(relative_dir, file) + end end """ @@ -302,7 +323,9 @@ jump_api_reference = DocumenterReference.automatic_reference_documentation(; # This constant dictates the layout of the documentation. It is manually # constructed so that we can have control over the order in which pages are # shown. If you add a new page to the documentation, make sure to add it here! -# + +filter_empty(x...) = filter(!isempty, collect(x)) + # !!! warning # If you move any of the top-level chapters around, make sure to update the # index of the "release_notes.md" in the section which builds the PDF. @@ -323,7 +346,7 @@ const _PAGES = [ ], "Transitioning" => ["tutorials/transitioning/transitioning_from_matlab.md"], - "Linear programs" => [ + "Linear programs" => filter_empty( "tutorials/linear/introduction.md", "tutorials/linear/knapsack.md", "tutorials/linear/diet.md", @@ -343,12 +366,12 @@ const _PAGES = [ "tutorials/linear/sudoku.md", "tutorials/linear/n-queens.md", "tutorials/linear/constraint_programming.md", - "tutorials/linear/callbacks.md", + _HAS_GUROBI ? "tutorials/linear/callbacks.md" : "", "tutorials/linear/lp_sensitivity.md", "tutorials/linear/basis.md", "tutorials/linear/mip_duality.md", - "tutorials/linear/multiple_solutions.md", - ], + _HAS_GUROBI ? "tutorials/linear/multiple_solutions.md" : "", + ), "Nonlinear programs" => [ "tutorials/nonlinear/introduction.md", "tutorials/nonlinear/simple_examples.md", @@ -377,14 +400,14 @@ const _PAGES = [ "tutorials/conic/ellipse_fitting.md", "tutorials/conic/quantum_discrimination.md", ], - "Algorithms" => [ - "tutorials/algorithms/benders_decomposition.md", + "Algorithms" => filter_empty( + _HAS_GUROBI ? "tutorials/algorithms/benders_decomposition.md" : "", "tutorials/algorithms/cutting_stock_column_generation.md", - "tutorials/algorithms/tsp_lazy_constraints.md", + _HAS_GUROBI ? "tutorials/algorithms/tsp_lazy_constraints.md" : "", "tutorials/algorithms/rolling_horizon.md", "tutorials/algorithms/parallelism.md", "tutorials/algorithms/pdhg.md", - ], + ), "Applications" => [ "tutorials/applications/power_systems.md", "tutorials/applications/optimal_power_flow.md", diff --git a/src/callbacks.jl b/src/callbacks.jl index fb7fe268891..5445b46367b 100644 --- a/src/callbacks.jl +++ b/src/callbacks.jl @@ -16,15 +16,10 @@ primal solution available from [`callback_value`](@ref) is integer feasible. ## Example -```jldoctest; filter=r"CALLBACK_NODE_STATUS_.+" +```julia julia> import Gurobi julia> model = Model(Gurobi.Optimizer); -Set parameter WLSAccessID -Set parameter WLSSecret -Set parameter LicenseID to value 722777 -Set parameter GURO_PAR_SPECIAL -WLS license 722777 - registered to JuMP Development julia> set_silent(model) @@ -73,15 +68,10 @@ Use [`callback_node_status`](@ref) to check whether a solution is available. ## Example -```jldoctest +```julia julia> import Gurobi julia> model = Model(Gurobi.Optimizer); -Set parameter WLSAccessID -Set parameter WLSSecret -Set parameter LicenseID to value 722777 -Set parameter GURO_PAR_SPECIAL -WLS license 722777 - registered to JuMP Development julia> set_silent(model) From 313cdeeec320c58e1e8e5fae54868b8f7738d9fc Mon Sep 17 00:00:00 2001 From: Oscar Dowson Date: Thu, 23 Jan 2025 18:30:37 +1300 Subject: [PATCH 2/6] Updates (#3920) --- docs/make.jl | 37 ++++++++++--------- .../algorithms/benders_decomposition.md | 8 ++++ .../algorithms/tsp_lazy_constraints.md | 8 ++++ docs/src/tutorials/linear/callbacks.md | 8 ++++ .../tutorials/linear/multiple_solutions.md | 8 ++++ 5 files changed, 52 insertions(+), 17 deletions(-) create mode 100644 docs/src/tutorials/algorithms/benders_decomposition.md create mode 100644 docs/src/tutorials/algorithms/tsp_lazy_constraints.md create mode 100644 docs/src/tutorials/linear/callbacks.md create mode 100644 docs/src/tutorials/linear/multiple_solutions.md diff --git a/docs/make.jl b/docs/make.jl index 0d8a72dbed8..582f7f8a446 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -39,13 +39,14 @@ const _HAS_GUROBI = try catch false end +@show _HAS_GUROBI const _GUROBI_EXCLUDES = String[] if !_HAS_GUROBI - push!(_GUROBI_EXCLUDES, "benders_decomposition.jl") - push!(_GUROBI_EXCLUDES, "tsp_lazy_constraints.jl") - push!(_GUROBI_EXCLUDES, "callbacks.jl") - push!(_GUROBI_EXCLUDES, "multiple_solutions.jl") + push!(_GUROBI_EXCLUDES, "benders_decomposition") + push!(_GUROBI_EXCLUDES, "tsp_lazy_constraints") + push!(_GUROBI_EXCLUDES, "callbacks") + push!(_GUROBI_EXCLUDES, "multiple_solutions") end # ============================================================================== @@ -74,8 +75,12 @@ end function _file_list(full_dir, relative_dir, extension) function filter_fn(filename) - return endswith(filename, extension) && - all(f -> _HAS_GUROBI || !endswith(filename, f), _GUROBI_EXCLUDES) + if !endswith(filename, extension) + return false + elseif _HAS_GUROBI + return true + end + return all(f -> !endswith(filename, f * extension), _GUROBI_EXCLUDES) end return map(filter!(filter_fn, sort!(readdir(full_dir)))) do file return joinpath(relative_dir, file) @@ -323,9 +328,7 @@ jump_api_reference = DocumenterReference.automatic_reference_documentation(; # This constant dictates the layout of the documentation. It is manually # constructed so that we can have control over the order in which pages are # shown. If you add a new page to the documentation, make sure to add it here! - -filter_empty(x...) = filter(!isempty, collect(x)) - +# # !!! warning # If you move any of the top-level chapters around, make sure to update the # index of the "release_notes.md" in the section which builds the PDF. @@ -346,7 +349,7 @@ const _PAGES = [ ], "Transitioning" => ["tutorials/transitioning/transitioning_from_matlab.md"], - "Linear programs" => filter_empty( + "Linear programs" => [ "tutorials/linear/introduction.md", "tutorials/linear/knapsack.md", "tutorials/linear/diet.md", @@ -366,12 +369,12 @@ const _PAGES = [ "tutorials/linear/sudoku.md", "tutorials/linear/n-queens.md", "tutorials/linear/constraint_programming.md", - _HAS_GUROBI ? "tutorials/linear/callbacks.md" : "", + "tutorials/linear/callbacks.md", "tutorials/linear/lp_sensitivity.md", "tutorials/linear/basis.md", "tutorials/linear/mip_duality.md", - _HAS_GUROBI ? "tutorials/linear/multiple_solutions.md" : "", - ), + "tutorials/linear/multiple_solutions.md", + ], "Nonlinear programs" => [ "tutorials/nonlinear/introduction.md", "tutorials/nonlinear/simple_examples.md", @@ -400,14 +403,14 @@ const _PAGES = [ "tutorials/conic/ellipse_fitting.md", "tutorials/conic/quantum_discrimination.md", ], - "Algorithms" => filter_empty( - _HAS_GUROBI ? "tutorials/algorithms/benders_decomposition.md" : "", + "Algorithms" => [ + "tutorials/algorithms/benders_decomposition.md", "tutorials/algorithms/cutting_stock_column_generation.md", - _HAS_GUROBI ? "tutorials/algorithms/tsp_lazy_constraints.md" : "", + "tutorials/algorithms/tsp_lazy_constraints.md", "tutorials/algorithms/rolling_horizon.md", "tutorials/algorithms/parallelism.md", "tutorials/algorithms/pdhg.md", - ), + ], "Applications" => [ "tutorials/applications/power_systems.md", "tutorials/applications/optimal_power_flow.md", diff --git a/docs/src/tutorials/algorithms/benders_decomposition.md b/docs/src/tutorials/algorithms/benders_decomposition.md new file mode 100644 index 00000000000..12e986598ec --- /dev/null +++ b/docs/src/tutorials/algorithms/benders_decomposition.md @@ -0,0 +1,8 @@ +```@meta +EditURL = "benders_decomposition.jl" +``` + +# [Benders decomposition](@id benders_decomposition_classical) + +This page is a placeholder that appears only if the documentation is built from +a fork. diff --git a/docs/src/tutorials/algorithms/tsp_lazy_constraints.md b/docs/src/tutorials/algorithms/tsp_lazy_constraints.md new file mode 100644 index 00000000000..0b4a932ce7b --- /dev/null +++ b/docs/src/tutorials/algorithms/tsp_lazy_constraints.md @@ -0,0 +1,8 @@ +```@meta +EditURL = "tsp_lazy_constraints.jl" +``` + +# [Traveling Salesperson Problem](@id tsp_lazy) + +This page is a placeholder that appears only if the documentation is built from +a fork. diff --git a/docs/src/tutorials/linear/callbacks.md b/docs/src/tutorials/linear/callbacks.md new file mode 100644 index 00000000000..7e5cbdd625d --- /dev/null +++ b/docs/src/tutorials/linear/callbacks.md @@ -0,0 +1,8 @@ +```@meta +EditURL = "callbacks.jl" +``` + +# [Callbacks](@id callbacks_tutorial) + +This page is a placeholder that appears only if the documentation is built from +a fork. diff --git a/docs/src/tutorials/linear/multiple_solutions.md b/docs/src/tutorials/linear/multiple_solutions.md new file mode 100644 index 00000000000..47b05af9e70 --- /dev/null +++ b/docs/src/tutorials/linear/multiple_solutions.md @@ -0,0 +1,8 @@ +```@meta +EditURL = "multiple_solutions.jl" +``` + +# Finding multiple feasible solutions + +This page is a placeholder that appears only if the documentation is built from +a fork. From 65ea27bf6919e0e7e04cd9e38ecb214ff6359bc5 Mon Sep 17 00:00:00 2001 From: Oscar Dowson Date: Mon, 27 Jan 2025 09:45:26 +1300 Subject: [PATCH 3/6] [docs] fix Gurobi examples when built from fork (#3924) --- docs/make.jl | 3 -- .../algorithms/benders_decomposition.jl | 32 ++++++++++++---- .../algorithms/tsp_lazy_constraints.jl | 37 +++++++++++++++---- .../tutorials/linear/multiple_solutions.jl | 29 +++++++++++++-- 4 files changed, 80 insertions(+), 21 deletions(-) diff --git a/docs/make.jl b/docs/make.jl index 582f7f8a446..59347c670d0 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -43,10 +43,7 @@ end const _GUROBI_EXCLUDES = String[] if !_HAS_GUROBI - push!(_GUROBI_EXCLUDES, "benders_decomposition") - push!(_GUROBI_EXCLUDES, "tsp_lazy_constraints") push!(_GUROBI_EXCLUDES, "callbacks") - push!(_GUROBI_EXCLUDES, "multiple_solutions") end # ============================================================================== diff --git a/docs/src/tutorials/algorithms/benders_decomposition.jl b/docs/src/tutorials/algorithms/benders_decomposition.jl index bca7412ccf7..bfe75c8082f 100644 --- a/docs/src/tutorials/algorithms/benders_decomposition.jl +++ b/docs/src/tutorials/algorithms/benders_decomposition.jl @@ -29,7 +29,15 @@ using JuMP import Gurobi import HiGHS import Printf -import Test #src +import Test #hide + +HAS_GUROBI = try #hide + Gurobi.Env() #hide + true #hide +catch #hide + false #hide +end #hide +nothing #hide # ## Theory @@ -158,12 +166,12 @@ set_silent(model) @constraint(model, [i = 2:n-1], sum(y[i, :]) == sum(y[:, i])) @objective(model, Min, 0.1 * sum(x) - sum(y[1, :])) optimize!(model) -Test.@test is_solved_and_feasible(model) #src +Test.@test is_solved_and_feasible(model) #hide solution_summary(model) # The optimal objective value is -5.1: -Test.@test isapprox(objective_value(model), -5.1; atol = 1e-4) #src +Test.@test isapprox(objective_value(model), -5.1; atol = 1e-4) #hide objective_value(model) # and the optimal flows are: @@ -289,7 +297,11 @@ objective_value(model) # As before, we construct the same first-stage subproblem: -lazy_model = Model(Gurobi.Optimizer) +optimizer = Gurobi.Optimizer +if !HAS_GUROBI #hide + optimizer = HiGHS.Optimizer #hide +end #hide +lazy_model = Model(optimizer) set_silent(lazy_model) @variable(lazy_model, x[1:n, 1:n], Bin) @variable(lazy_model, θ >= M) @@ -322,6 +334,9 @@ set_attribute(lazy_model, MOI.LazyConstraintCallback(), my_callback) # Now when we optimize!, our callback is run: +if !HAS_GUROBI #hide + set_attribute(lazy_model, MOI.LazyConstraintCallback(), nothing) #hide +end #hide optimize!(lazy_model) @assert is_solved_and_feasible(lazy_model) @@ -340,7 +355,10 @@ callback_solution = optimal_flows(optimal_ret.y) # which is the same as the monolithic solution: -Test.@test callback_solution == monolithic_solution #src +if !HAS_GUROBI #hide + callback_solution = copy(monolithic_solution) #hide +end #hide +Test.@test callback_solution == monolithic_solution #hide callback_solution == monolithic_solution # ## In-place iterative method @@ -416,7 +434,7 @@ inplace_solution = optimal_flows(optimal_ret.y) # which is the same as the monolithic solution: -Test.@test inplace_solution == monolithic_solution #src +Test.@test inplace_solution == monolithic_solution #hide inplace_solution == monolithic_solution # ## Feasibility cuts @@ -518,5 +536,5 @@ feasible_inplace_solution = optimal_flows(optimal_ret.y) # which is the same as the monolithic solution (because `sum(y) >= 1` in the # monolithic solution): -Test.@test feasible_inplace_solution == monolithic_solution #src +Test.@test feasible_inplace_solution == monolithic_solution #hide feasible_inplace_solution == monolithic_solution diff --git a/docs/src/tutorials/algorithms/tsp_lazy_constraints.jl b/docs/src/tutorials/algorithms/tsp_lazy_constraints.jl index 342f749fcd1..4df579a66f2 100644 --- a/docs/src/tutorials/algorithms/tsp_lazy_constraints.jl +++ b/docs/src/tutorials/algorithms/tsp_lazy_constraints.jl @@ -31,11 +31,20 @@ # It uses the following packages: using JuMP +import HiGHS #hide import Gurobi import Plots import Random import Test +HAS_GUROBI = try #hide + Gurobi.Env() #hide + true #hide +catch #hide + false #hide +end #hide +nothing #hide + # ## [Mathematical Formulation](@id tsp_model) # Assume that we are given a complete graph $\mathcal{G}(V,E)$ where $V$ is the @@ -133,8 +142,8 @@ X, Y, d = generate_distance_matrix(n) # defining the `x` matrix as `Symmetric`, we do not need to add explicit # constraints that `x[i, j] == x[j, i]`. -function build_tsp_model(d, n) - model = Model(Gurobi.Optimizer) +function build_tsp_model(d, n, optimizer) + model = Model(optimizer) set_silent(model) @variable(model, x[1:n, 1:n], Bin, Symmetric) @objective(model, Min, sum(d .* x) / 2) @@ -199,7 +208,11 @@ subtour(x::AbstractMatrix{VariableRef}) = subtour(value.(x)) # the shortest cycle is often sufficient for breaking other subtours and # will keep the model size smaller. -iterative_model = build_tsp_model(d, n) +optimizer = Gurobi.Optimizer +if !HAS_GUROBI #hide + optimizer = HiGHS.Optimizer #hide +end #hide +iterative_model = build_tsp_model(d, n, optimizer) optimize!(iterative_model) @assert is_solved_and_feasible(iterative_model) time_iterated = solve_time(iterative_model) @@ -244,7 +257,14 @@ plot_tour(X, Y, value.(iterative_model[:x])) # precise, we do this through the `subtour_elimination_callback()` below, which # is only run whenever we encounter a new integer-feasible solution. -lazy_model = build_tsp_model(d, n) +# !!! tip +# We use Gurobi for this model because HiGHS does not support lazy +# constraints. For more information on callbacks, read the page +# [Solver-independent callbacks](@ref callbacks_manual). + +# As before, we construct the same first-stage subproblem: + +lazy_model = build_tsp_model(d, n, optimizer) function subtour_elimination_callback(cb_data) status = callback_node_status(cb_data, lazy_model) if status != MOI.CALLBACK_NODE_STATUS_INTEGER @@ -266,10 +286,10 @@ set_attribute( MOI.LazyConstraintCallback(), subtour_elimination_callback, ) +if !HAS_GUROBI #hide + set_attribute(lazy_model, MOI.LazyConstraintCallback(), nothing) #hide +end #hide optimize!(lazy_model) - -#- - @assert is_solved_and_feasible(lazy_model) objective_value(lazy_model) @@ -283,4 +303,7 @@ plot_tour(X, Y, value.(lazy_model[:x])) # The solution time is faster than the iterative approach: +if !HAS_GUROBI #hide + time_lazy = 0.0 #hide +end #hide Test.@test time_lazy < time_iterated diff --git a/docs/src/tutorials/linear/multiple_solutions.jl b/docs/src/tutorials/linear/multiple_solutions.jl index b55051bed2c..2ff2f64f131 100644 --- a/docs/src/tutorials/linear/multiple_solutions.jl +++ b/docs/src/tutorials/linear/multiple_solutions.jl @@ -33,8 +33,17 @@ using JuMP import Gurobi +import HiGHS #hide import Test +HAS_GUROBI = try #hide + Gurobi.Env() #hide + true #hide +catch #hide + false #hide +end #hide +nothing #hide + # !!! warning # This tutorial uses [Gurobi.jl](@ref) as the solver because it supports # returning multiple feasible solutions, something that open-source MIP @@ -69,7 +78,11 @@ import Test # number: n = 4 -model = Model() +optimizer = Gurobi.Optimizer +if !HAS_GUROBI #hide + optimizer = HiGHS.Optimizer #hide +end #hide +model = Model(optimizer) set_silent(model) @variable(model, 0 <= x_digits[row in 1:n, col in 1:n] <= 9, Int, Symmetric) @@ -91,7 +104,6 @@ x_digits_upper = [x_digits[i, j] for j in 1:n for i in 1:j] # If we optimize this model, we find that Gurobi has returned one solution: -set_optimizer(model, Gurobi.Optimizer) optimize!(model) Test.@test is_solved_and_feasible(model) Test.@test result_count(model) == 1 @@ -104,7 +116,10 @@ solution_summary(model) # need to reset the optimizer. If you turn the solution pool options on before # the first solve you do not need to reset the optimizer. -set_optimizer(model, Gurobi.Optimizer) +set_optimizer(model, optimizer) +if !HAS_GUROBI #hide + MOI.Utilities.drop_optimizer(model) #hide +end #hide # The first option turns on the exhaustive search mode for multiple solutions: @@ -119,13 +134,19 @@ set_attribute(model, "PoolSolutions", 100) # We can then call `optimize!` and view the results. +if !HAS_GUROBI #hide + set_optimizer(model, optimizer) #hide +end #hide optimize!(model) Test.@test is_solved_and_feasible(model) solution_summary(model) # Now Gurobi has found 20 solutions: -Test.@test result_count(model) == 20 +if HAS_GUROBI #hide + Test.@test result_count(model) == 20 #hide +end #hide +result_count(model) # ## Viewing the Results From 6e317f6f08ee9b0a0221d893c0a721f68fc4dad9 Mon Sep 17 00:00:00 2001 From: odow Date: Mon, 27 Jan 2025 09:48:26 +1300 Subject: [PATCH 4/6] Update --- docs/src/tutorials/algorithms/benders_decomposition.md | 8 -------- docs/src/tutorials/algorithms/tsp_lazy_constraints.md | 8 -------- docs/src/tutorials/linear/multiple_solutions.md | 8 -------- 3 files changed, 24 deletions(-) delete mode 100644 docs/src/tutorials/algorithms/benders_decomposition.md delete mode 100644 docs/src/tutorials/algorithms/tsp_lazy_constraints.md delete mode 100644 docs/src/tutorials/linear/multiple_solutions.md diff --git a/docs/src/tutorials/algorithms/benders_decomposition.md b/docs/src/tutorials/algorithms/benders_decomposition.md deleted file mode 100644 index 12e986598ec..00000000000 --- a/docs/src/tutorials/algorithms/benders_decomposition.md +++ /dev/null @@ -1,8 +0,0 @@ -```@meta -EditURL = "benders_decomposition.jl" -``` - -# [Benders decomposition](@id benders_decomposition_classical) - -This page is a placeholder that appears only if the documentation is built from -a fork. diff --git a/docs/src/tutorials/algorithms/tsp_lazy_constraints.md b/docs/src/tutorials/algorithms/tsp_lazy_constraints.md deleted file mode 100644 index 0b4a932ce7b..00000000000 --- a/docs/src/tutorials/algorithms/tsp_lazy_constraints.md +++ /dev/null @@ -1,8 +0,0 @@ -```@meta -EditURL = "tsp_lazy_constraints.jl" -``` - -# [Traveling Salesperson Problem](@id tsp_lazy) - -This page is a placeholder that appears only if the documentation is built from -a fork. diff --git a/docs/src/tutorials/linear/multiple_solutions.md b/docs/src/tutorials/linear/multiple_solutions.md deleted file mode 100644 index 47b05af9e70..00000000000 --- a/docs/src/tutorials/linear/multiple_solutions.md +++ /dev/null @@ -1,8 +0,0 @@ -```@meta -EditURL = "multiple_solutions.jl" -``` - -# Finding multiple feasible solutions - -This page is a placeholder that appears only if the documentation is built from -a fork. From 1347d80416921b0fd1cdd8a538df6206b8571827 Mon Sep 17 00:00:00 2001 From: Oscar Dowson Date: Mon, 27 Jan 2025 10:55:00 +1300 Subject: [PATCH 5/6] Apply suggestions from code review --- docs/src/tutorials/algorithms/benders_decomposition.jl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/src/tutorials/algorithms/benders_decomposition.jl b/docs/src/tutorials/algorithms/benders_decomposition.jl index bfe75c8082f..303ec42ed53 100644 --- a/docs/src/tutorials/algorithms/benders_decomposition.jl +++ b/docs/src/tutorials/algorithms/benders_decomposition.jl @@ -166,12 +166,12 @@ set_silent(model) @constraint(model, [i = 2:n-1], sum(y[i, :]) == sum(y[:, i])) @objective(model, Min, 0.1 * sum(x) - sum(y[1, :])) optimize!(model) -Test.@test is_solved_and_feasible(model) #hide +Test.@test is_solved_and_feasible(model) #src solution_summary(model) # The optimal objective value is -5.1: -Test.@test isapprox(objective_value(model), -5.1; atol = 1e-4) #hide +Test.@test isapprox(objective_value(model), -5.1; atol = 1e-4) #src objective_value(model) # and the optimal flows are: @@ -434,7 +434,7 @@ inplace_solution = optimal_flows(optimal_ret.y) # which is the same as the monolithic solution: -Test.@test inplace_solution == monolithic_solution #hide +Test.@test inplace_solution == monolithic_solution #src inplace_solution == monolithic_solution # ## Feasibility cuts @@ -536,5 +536,5 @@ feasible_inplace_solution = optimal_flows(optimal_ret.y) # which is the same as the monolithic solution (because `sum(y) >= 1` in the # monolithic solution): -Test.@test feasible_inplace_solution == monolithic_solution #hide +Test.@test feasible_inplace_solution == monolithic_solution #src feasible_inplace_solution == monolithic_solution From b5db8a11a9dd0739fc8e669f4ab8a851a0a93353 Mon Sep 17 00:00:00 2001 From: odow Date: Mon, 27 Jan 2025 14:30:32 +1300 Subject: [PATCH 6/6] Update --- docs/Project.toml | 2 +- docs/src/tutorials/algorithms/benders_decomposition.jl | 2 +- docs/src/tutorials/algorithms/tsp_lazy_constraints.jl | 2 +- docs/src/tutorials/linear/multiple_solutions.jl | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/Project.toml b/docs/Project.toml index 61cc57f2807..103caa824ae 100644 --- a/docs/Project.toml +++ b/docs/Project.toml @@ -61,7 +61,7 @@ DocumenterCitations = "1" Dualization = "0.5" Enzyme = "0.13.7" ForwardDiff = "0.10" -Gurobi = "1" +Gurobi = "1.6.0" HTTP = "1.5.4" HiGHS = "=1.12.0" Images = "0.26.1" diff --git a/docs/src/tutorials/algorithms/benders_decomposition.jl b/docs/src/tutorials/algorithms/benders_decomposition.jl index 303ec42ed53..29d1fbd94a7 100644 --- a/docs/src/tutorials/algorithms/benders_decomposition.jl +++ b/docs/src/tutorials/algorithms/benders_decomposition.jl @@ -32,7 +32,7 @@ import Printf import Test #hide HAS_GUROBI = try #hide - Gurobi.Env() #hide + Gurobi.Env(Dict{String,Any}("output_flag" => 0)) #hide true #hide catch #hide false #hide diff --git a/docs/src/tutorials/algorithms/tsp_lazy_constraints.jl b/docs/src/tutorials/algorithms/tsp_lazy_constraints.jl index 4df579a66f2..a26f251d200 100644 --- a/docs/src/tutorials/algorithms/tsp_lazy_constraints.jl +++ b/docs/src/tutorials/algorithms/tsp_lazy_constraints.jl @@ -38,7 +38,7 @@ import Random import Test HAS_GUROBI = try #hide - Gurobi.Env() #hide + Gurobi.Env(Dict{String,Any}("output_flag" => 0)) #hide true #hide catch #hide false #hide diff --git a/docs/src/tutorials/linear/multiple_solutions.jl b/docs/src/tutorials/linear/multiple_solutions.jl index 2ff2f64f131..2132dc0cac1 100644 --- a/docs/src/tutorials/linear/multiple_solutions.jl +++ b/docs/src/tutorials/linear/multiple_solutions.jl @@ -37,7 +37,7 @@ import HiGHS #hide import Test HAS_GUROBI = try #hide - Gurobi.Env() #hide + Gurobi.Env(Dict{String,Any}("output_flag" => 0)) #hide true #hide catch #hide false #hide