diff --git a/docs/make.jl b/docs/make.jl index ca92743ec..167020681 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -173,7 +173,8 @@ Documenter.makedocs(; "guides/choose_a_stopping_rule.md", "guides/create_a_general_policy_graph.md", "guides/add_a_custom_cut.md", - "guides/debug_a_model.md", + "guides/write_subproblems_to_file.md", + "guides/deterministic_equivalent.md", "guides/improve_computational_performance.md", "guides/simulate_using_a_different_sampling_scheme.md", "guides/create_a_belief_state.md", diff --git a/docs/src/changelog.md b/docs/src/changelog.md index 44628bae7..54dfa63f5 100644 --- a/docs/src/changelog.md +++ b/docs/src/changelog.md @@ -76,8 +76,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Other - - Added documentation [Add a custom cut](@ref) (#832) - - Added documentation [Use multithreading](@ref) (#833) + - Added documentation [How to add a custom cut](@ref) (#832) + - Added documentation [How to use multithreading](@ref) (#833) - Fixed a typo in [Risk aversion](@ref) (#835) - Changed to use `test/Project.toml` (#837) - Debug and work around a bug in `HiGHS_jll@1.10` (#836), (#839) diff --git a/docs/src/examples/the_farmers_problem.jl b/docs/src/examples/the_farmers_problem.jl index 6b86686e2..b1686c1cb 100644 --- a/docs/src/examples/the_farmers_problem.jl +++ b/docs/src/examples/the_farmers_problem.jl @@ -247,7 +247,7 @@ end # Now that we've built a model, we need to train it using [`SDDP.train`](@ref). # The keyword `iteration_limit` stops the training after 40 iterations. See -# [Choose a stopping rule](@ref) for other ways to stop the training. +# [How to choose a stopping rule](@ref) for other ways to stop the training. SDDP.train(model; iteration_limit = 40) diff --git a/docs/src/explanation/risk.jl b/docs/src/explanation/risk.jl index e1881f21b..5ec7e7971 100644 --- a/docs/src/explanation/risk.jl +++ b/docs/src/explanation/risk.jl @@ -387,7 +387,7 @@ end # This method of solving the dual problem "on-the-side" is used by SDDP.jl # for a number of risk measures, including a distributionally robust risk # measure with the Wasserstein distance. Check out all the risk measures -# that SDDP.jl supports in [Add a risk measure](@ref). +# that SDDP.jl supports in [How to add a risk measure](@ref). # The "on-the-side" method is very general, and it lets us incorporate any # convex risk measure into SDDP. However, this comes at an increased diff --git a/docs/src/guides/access_previous_variables.md b/docs/src/guides/access_previous_variables.md index f3fbe90f8..4795efafa 100644 --- a/docs/src/guides/access_previous_variables.md +++ b/docs/src/guides/access_previous_variables.md @@ -1,4 +1,4 @@ -# Access variables from a previous stage +# How to access variables from a previous stage A common question is "how do I use a variable from a previous stage in a constraint?" @@ -55,8 +55,8 @@ end ## Access a decision from N stages ago This is often useful if you have some inventory problem with a lead time on orders. -In the code below, we assume that the product has a lead time of 5 stages, and we -use a state variable to track the decisions on the production for the last 5 stages. +In the code below, we assume that the product has a lead time of 5 stages, and we +use a state variable to track the decisions on the production for the last 5 stages. The decisions are passed to the next stage by shifting them by one stage. ```@repl @@ -129,7 +129,7 @@ model = SDDP.LinearPolicyGraph( fix(x_pipeline[T+1].out, 0) @stageobjective(sp, u_sell) @constraints(sp, begin - # Shift the orders one stage + # Shift the orders one stage c_pipeline[i=1:T], x_pipeline[i].out == x_pipeline[i+1].in + 1 * u_buy # x_pipeline[1].in are arriving on the inventory x_inventory.out == x_inventory.in - u_sell + x_pipeline[1].in diff --git a/docs/src/guides/add_a_custom_cut.md b/docs/src/guides/add_a_custom_cut.md index bcd017624..422f52d28 100644 --- a/docs/src/guides/add_a_custom_cut.md +++ b/docs/src/guides/add_a_custom_cut.md @@ -1,4 +1,4 @@ -# Add a custom cut +# How to add a custom cut Sometimes you may want to add a set of cuts to the value function that you have computed outside of SDDP.jl. The easiest way to achieve this is via the diff --git a/docs/src/guides/add_a_multidimensional_state_variable.md b/docs/src/guides/add_a_multidimensional_state_variable.md index 40e707aa4..7eaa31ce5 100644 --- a/docs/src/guides/add_a_multidimensional_state_variable.md +++ b/docs/src/guides/add_a_multidimensional_state_variable.md @@ -1,4 +1,4 @@ -# Add a multi-dimensional state variable +# How to add a multi-dimensional state variable ```@meta DocTestSetup = quote diff --git a/docs/src/guides/add_a_risk_measure.md b/docs/src/guides/add_a_risk_measure.md index 5dfffcf38..c02261a3c 100644 --- a/docs/src/guides/add_a_risk_measure.md +++ b/docs/src/guides/add_a_risk_measure.md @@ -1,4 +1,4 @@ -# Add a risk measure +# How to add a risk measure ```@meta DocTestSetup = quote diff --git a/docs/src/guides/add_integrality.md b/docs/src/guides/add_integrality.md index 1a91a4b71..377b1718b 100644 --- a/docs/src/guides/add_integrality.md +++ b/docs/src/guides/add_integrality.md @@ -2,7 +2,7 @@ CurrentModule = SDDP ``` -# Integrality +# How to add integrality There's nothing special about binary and integer variables in SDDP.jl. Your models may contain a mix of binary, integer, and continuous state and control diff --git a/docs/src/guides/add_multidimensional_noise.md b/docs/src/guides/add_multidimensional_noise.md index baa02eb77..d70e7c9ef 100644 --- a/docs/src/guides/add_multidimensional_noise.md +++ b/docs/src/guides/add_multidimensional_noise.md @@ -1,4 +1,4 @@ -# Add multi-dimensional noise terms +# How to add multi-dimensional noise terms ```@meta DocTestSetup = quote diff --git a/docs/src/guides/add_noise_in_the_constraint_matrix.md b/docs/src/guides/add_noise_in_the_constraint_matrix.md index 31131185c..8f16bf306 100644 --- a/docs/src/guides/add_noise_in_the_constraint_matrix.md +++ b/docs/src/guides/add_noise_in_the_constraint_matrix.md @@ -1,4 +1,4 @@ -# Add noise in the constraint matrix +# How to add noise in the constraint matrix ```@meta DocTestSetup = quote diff --git a/docs/src/guides/choose_a_stopping_rule.md b/docs/src/guides/choose_a_stopping_rule.md index e3c3bbbf3..2476ab0d1 100644 --- a/docs/src/guides/choose_a_stopping_rule.md +++ b/docs/src/guides/choose_a_stopping_rule.md @@ -1,4 +1,4 @@ -# Choose a stopping rule +# How to choose a stopping rule The theory of SDDP tells us that the algorithm converges to an optimal policy almost surely in a finite number of iterations. In practice, this number is very diff --git a/docs/src/guides/create_a_belief_state.md b/docs/src/guides/create_a_belief_state.md index 8517e019c..8923123ab 100644 --- a/docs/src/guides/create_a_belief_state.md +++ b/docs/src/guides/create_a_belief_state.md @@ -4,13 +4,13 @@ DocTestSetup = quote end ``` -# Create a belief state +# How to create a belief state `SDDP.jl` includes an implementation of the algorithm described in Dowson, O., Morton, D.P., & Pagnoncelli, B.K. (2020). Partially observable multistage stochastic optimization. _Operations Research Letters_, 48(4), 505--512. -Given a [`SDDP.Graph`](@ref) object (see [Create a general policy graph](@ref) +Given a [`SDDP.Graph`](@ref) object (see [How to create a general policy graph](@ref) for details), we can define the ambiguity partition using [`SDDP.add_ambiguity_set`](@ref). diff --git a/docs/src/guides/create_a_general_policy_graph.md b/docs/src/guides/create_a_general_policy_graph.md index 9a9b58d17..0e6560209 100644 --- a/docs/src/guides/create_a_general_policy_graph.md +++ b/docs/src/guides/create_a_general_policy_graph.md @@ -1,4 +1,4 @@ -# Create a general policy graph +# How to create a general policy graph ```@meta DocTestSetup = quote @@ -186,7 +186,7 @@ simulations = SDDP.simulate( Here, `max_depth` controls the number of stages, and `terminate_on_dummy_leaf = false` stops us from terminating early. -See also [Simulate using a different sampling scheme](@ref). +See also [How to simulate using a different sampling scheme](@ref). ## Creating a Markovian graph automatically diff --git a/docs/src/guides/deterministic_equivalent.md b/docs/src/guides/deterministic_equivalent.md new file mode 100644 index 000000000..abbc87333 --- /dev/null +++ b/docs/src/guides/deterministic_equivalent.md @@ -0,0 +1,51 @@ +# How to solve the deterministic equivalent + +Sometimes, it can be helpful to solve the deterministic equivalent of a +problem in order to obtain an exact solution to the problem. To obtain a JuMP +model that represents the deterministic equivalent, use [`SDDP.deterministic_equivalent`](@ref). +The returned model is just a normal JuMP model. Use JuMP to optimize it and +query the solution. + +```jldoctest; filter=r"5.4725[0]+[0-9]" +julia> using SDDP, HiGHS + +julia> model = SDDP.LinearPolicyGraph( + stages = 2, + lower_bound = 0.0, + optimizer = HiGHS.Optimizer, + ) do subproblem, t + @variable(subproblem, x, SDDP.State, initial_value = 1) + @variable(subproblem, y) + @constraint(subproblem, balance, x.in == x.out + y) + SDDP.parameterize(subproblem, [1.1, 2.2]) do ω + @stageobjective(subproblem, ω * x.out) + fix(y, ω) + end + end +A policy graph with 2 nodes. + Node indices: 1, 2 + +julia> det_equiv = SDDP.deterministic_equivalent(model, HiGHS.Optimizer) +A JuMP Model +├ solver: HiGHS +├ objective_sense: MIN_SENSE +│ └ objective_function_type: AffExpr +├ num_variables: 24 +├ num_constraints: 28 +│ ├ AffExpr in MOI.EqualTo{Float64}: 10 +│ ├ VariableRef in MOI.EqualTo{Float64}: 8 +│ ├ VariableRef in MOI.GreaterThan{Float64}: 6 +│ └ VariableRef in MOI.LessThan{Float64}: 4 +└ Names registered in the model: none + +julia> set_silent(det_equiv) + +julia> optimize!(det_equiv) + +julia> objective_value(det_equiv) +-5.472500000000001 +``` + +!!! warning + The deterministic equivalent scales poorly with problem size. Only use this + on small problems! diff --git a/docs/src/guides/improve_computational_performance.md b/docs/src/guides/improve_computational_performance.md index d581feb3e..b22014bdb 100644 --- a/docs/src/guides/improve_computational_performance.md +++ b/docs/src/guides/improve_computational_performance.md @@ -1,4 +1,4 @@ -# Improve computational performance +# How to improve computational performance SDDP is a computationally intensive algorithm. Here are some suggestions for how the computational performance can be improved. diff --git a/docs/src/guides/simulate_using_a_different_sampling_scheme.md b/docs/src/guides/simulate_using_a_different_sampling_scheme.md index d68a36fba..52bc8c0cf 100644 --- a/docs/src/guides/simulate_using_a_different_sampling_scheme.md +++ b/docs/src/guides/simulate_using_a_different_sampling_scheme.md @@ -1,4 +1,4 @@ -# Simulate using a different sampling scheme +# How to simulate using a different sampling scheme ```@meta DocTestSetup = quote diff --git a/docs/src/guides/use_multithreading.md b/docs/src/guides/use_multithreading.md index e3104f10f..61eccf775 100644 --- a/docs/src/guides/use_multithreading.md +++ b/docs/src/guides/use_multithreading.md @@ -1,4 +1,4 @@ -# Use multithreading +# How to use multithreading SDDP.jl can take advantage of the parallel nature of modern computers to solve problems across multiple threads. diff --git a/docs/src/guides/debug_a_model.md b/docs/src/guides/write_subproblems_to_file.md similarity index 61% rename from docs/src/guides/debug_a_model.md rename to docs/src/guides/write_subproblems_to_file.md index 10582de93..f29e49af3 100644 --- a/docs/src/guides/debug_a_model.md +++ b/docs/src/guides/write_subproblems_to_file.md @@ -1,13 +1,4 @@ -# Debug a model - -Building multistage stochastic programming models is hard. There are a lot of -different pieces that need to be put together, and we typically have no idea of -the optimal policy, so it can be hard (impossible?) to validate the solution. - -That said, here are a few tips to verify and validate models built using -`SDDP.jl`. - -## Writing subproblems to file +# How to write subproblems to file The first step to debug a model is to write out the subproblems to a file in order to check that you are actually building what you think you are building. @@ -92,37 +83,3 @@ End julia> rm("subproblem.lp") # Clean up. ``` - -## Solve the deterministic equivalent - -Sometimes, it can be helpful to solve the deterministic equivalent of a -problem in order to obtain an exact solution to the problem. To obtain a JuMP -model that represents the deterministic equivalent, use [`SDDP.deterministic_equivalent`](@ref). -The returned model is just a normal JuMP model. Use JuMP to optimize it and -query the solution. - -```jldoctest tutorial_eight; filter=r"5.4725[0]+[0-9]" -julia> det_equiv = SDDP.deterministic_equivalent(model, HiGHS.Optimizer) -A JuMP Model -├ solver: HiGHS -├ objective_sense: MIN_SENSE -│ └ objective_function_type: AffExpr -├ num_variables: 24 -├ num_constraints: 28 -│ ├ AffExpr in MOI.EqualTo{Float64}: 10 -│ ├ VariableRef in MOI.EqualTo{Float64}: 8 -│ ├ VariableRef in MOI.GreaterThan{Float64}: 6 -│ └ VariableRef in MOI.LessThan{Float64}: 4 -└ Names registered in the model: none - -julia> set_silent(det_equiv) - -julia> optimize!(det_equiv) - -julia> objective_value(det_equiv) --5.472500000000001 -``` - -!!! warning - The deterministic equivalent scales poorly with problem size. Only use this - on small problems! diff --git a/docs/src/index.md b/docs/src/index.md index a8d32ac2e..1d639ca76 100644 --- a/docs/src/index.md +++ b/docs/src/index.md @@ -63,7 +63,7 @@ you know where to look for certain things. you've got `SDDP.jl` installed, start by reading [An introduction to SDDP.jl](@ref). * **Guides** contains "how-to" snippets that demonstrate specific topics within - SDDP.jl. A good one to get started on is [Debug a model](@ref). + SDDP.jl. A good one to get started on is [How to add a risk measure](@ref). * **Explanation** contains step-by-step explanations of the theory and algorithms that underpin SDDP.jl. If you want a basic understanding of the diff --git a/docs/src/tutorial/duality_handlers.jl b/docs/src/tutorial/duality_handlers.jl index 3668743bd..0733f7f91 100644 --- a/docs/src/tutorial/duality_handlers.jl +++ b/docs/src/tutorial/duality_handlers.jl @@ -9,7 +9,7 @@ # The purpose of this tutorial is to demonstrate trivial examples that expose # the strengths and weaknesses of each duality handler. -# For more information on SDDP.jl's duality handlers, see [Integrality](@ref). +# For more information on SDDP.jl's duality handlers, see [How to add integrality](@ref). # This tutorial uses the following packages: diff --git a/docs/src/tutorial/first_steps.jl b/docs/src/tutorial/first_steps.jl index 5e1342f53..60bd95ccc 100644 --- a/docs/src/tutorial/first_steps.jl +++ b/docs/src/tutorial/first_steps.jl @@ -497,7 +497,7 @@ end # !!! warning # [`SDDP.parameterize`](@ref) can only be called once in each subproblem # definition! If your random variable is multi-variate, read -# [Add multi-dimensional noise terms](@ref). +# [How to add multi-dimensional noise terms](@ref). # #### Transition function and constraints diff --git a/docs/src/tutorial/markov_uncertainty.jl b/docs/src/tutorial/markov_uncertainty.jl index 842945ee0..a1852a3b1 100644 --- a/docs/src/tutorial/markov_uncertainty.jl +++ b/docs/src/tutorial/markov_uncertainty.jl @@ -107,7 +107,7 @@ end # !!! tip # For more information on [`SDDP.MarkovianPolicyGraph`](@ref)s, read -# [Create a general policy graph](@ref). +# [How to create a general policy graph](@ref). # ## Training and simulating the policy