diff --git a/docs/Project.toml b/docs/Project.toml index 9acefec..46aa1d5 100644 --- a/docs/Project.toml +++ b/docs/Project.toml @@ -11,7 +11,6 @@ OptimalControl = "5f98b655-cc9a-415a-b60e-744165666948" OrdinaryDiffEq = "1dea7af3-3e70-54e6-95c3-0bf5283fa5ed" Plots = "91a5bcdd-55d7-5caf-9e0b-520d859cae80" Suppressor = "fd094767-a336-5f1f-9728-57cf17d0bbfb" -Tutorials = "cb10daa6-a5e5-4c25-a171-ae181b8ea3c9" [compat] DifferentiationInterface = "0.6" diff --git a/docs/make.jl b/docs/make.jl index a12d309..a557b14 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -8,7 +8,7 @@ makedocs(; sitename="Tutorials", format=Documenter.HTML(; repolink="https://" * repo_url, - prettyurls=true, + prettyurls=false, size_threshold_ignore=[ "" ], diff --git a/docs/src/tutorial-continuation.md b/docs/src/tutorial-continuation.md index cd8e6bb..6fb9971 100644 --- a/docs/src/tutorial-continuation.md +++ b/docs/src/tutorial-continuation.md @@ -12,7 +12,7 @@ This usually gives better and faster convergence than solving each problem with The most compact syntax to perform a discrete continuation is to use a function that returns the OCP for a given value of the continuation parameter, and solve a sequence of these problems. We illustrate this on a very basic double integrator with increasing fixed final time. -First we load the required packages +First we load the required packages: ```@example main using OptimalControl @@ -21,7 +21,7 @@ using Printf using Plots ``` -and write a function that returns the OCP for a given final time +and write a function that returns the OCP for a given final time: ```@example main function ocp_T(T) diff --git a/docs/src/tutorial-discretisation.md b/docs/src/tutorial-discretisation.md index 85c6d51..2e3ad79 100644 --- a/docs/src/tutorial-discretisation.md +++ b/docs/src/tutorial-discretisation.md @@ -5,7 +5,8 @@ When calling `solve`, the option `disc_method=...` can be used to set the discre In addition to the default implicit `:trapeze` method (aka Crank-Nicolson), other choices are available, namely implicit `:midpoint` and the Gauss-Legendre collocations with 2 and stages, `:gauss_legendre_2` and `:gauss_legendre_3`, of order 4 and 6 respectively. Note that higher order methods will typically lead to larger NLP problems for the same number of time steps, and that accuracy will also depend on the smoothness of the problem. -As an example we will use the [Goddard problem](@ref tutorial-goddard) +As an example we will use the [Goddard problem](@ref tutorial-goddard). + ```@example main using OptimalControl # to define the optimal control problem and more using NLPModelsIpopt # to solve the problem via a direct method @@ -57,23 +58,28 @@ nothing # hide ``` Now let us compare different discretisations ```@example main +x_style = (legend=:none,) +p_style = (legend=:none,) + sol_trapeze = solve(ocp; tol=1e-8) -plot(sol_trapeze) +plt = plot(sol_trapeze; solution_label="trapeze", state_style=x_style, costate_style=p_style) sol_midpoint = solve(ocp, disc_method=:midpoint; tol=1e-8) -plot!(sol_midpoint) +plot!(plt, sol_midpoint; solution_label="midpoint", state_style=x_style, costate_style=p_style); sol_euler = solve(ocp, disc_method=:euler; tol=1e-8) -plot!(sol_euler) +plot!(plt, sol_euler; solution_label="euler", state_style=x_style, costate_style=p_style); sol_euler_imp = solve(ocp, disc_method=:euler_implicit; tol=1e-8) -plot!(sol_euler_imp) +plot!(plt, sol_euler_imp; solution_label="euler implicit", state_style=x_style, costate_style=p_style); sol_gl2 = solve(ocp, disc_method=:gauss_legendre_2; tol=1e-8) -plot!(sol_gl2) +plot!(plt, sol_gl2; solution_label="gauss legendre 2", state_style=x_style, costate_style=p_style); sol_gl3 = solve(ocp, disc_method=:gauss_legendre_3; tol=1e-8) -plot!(sol_gl3) +plot!(plt, sol_gl3; solution_label="gauss legendre 3", state_style=x_style, costate_style=p_style); + +plot(plt, size=(800, 800)) ``` ## Large problems and AD backend diff --git a/docs/src/tutorial-goddard.md b/docs/src/tutorial-goddard.md index 5a66257..33ce597 100644 --- a/docs/src/tutorial-goddard.md +++ b/docs/src/tutorial-goddard.md @@ -34,9 +34,9 @@ $v(t) \leq v_{\max}$. The initial state is fixed while only the final mass is pr as well as constrained arcs due to the path constraint on the velocity (see below). We import the [OptimalControl.jl](https://control-toolbox.org/OptimalControl.jl) package to define the optimal control problem and -[NLPModelsIpopt.jl](https://github.com/JuliaSmoothOptimizers/NLPModelsIpopt.jl) to solve it. -We import the [Plots.jl](https://github.com/JuliaPlots/Plots.jl) package to plot the solution. -The [OrdinaryDiffEq.jl](https://github.com/SciML/OrdinaryDiffEq.jl) package is used to +[NLPModelsIpopt.jl](https://jso.dev/NLPModelsIpopt.jl) to solve it. +We import the [Plots.jl](https://docs.juliaplots.org) package to plot the solution. +The [OrdinaryDiffEq.jl](https://docs.sciml.ai/OrdinaryDiffEq) package is used to define the shooting function for the indirect method and the [MINPACK.jl](https://github.com/sglyon/MINPACK.jl) package permits to solve the shooting equation. ```@example main @@ -119,15 +119,11 @@ bang arc with maximal control, followed by a singular arc, then by a boundary ar arc is with zero control. Note that the switching function vanishes along the singular and boundary arcs. -!!! tip "Interactions with an optimal control solution" - - Please check [`state`](@ref), [`costate`](@ref), [`control`](@ref) and [`variable`](@ref) to get data from the solution. The functions `state`, `costate` and `control` return functions of time and `variable` returns a vector. The function [`time_grid`](@ref) returns the discretized time grid returned by the solver. - ```@example main -t = time_grid(direct_sol) -x = state(direct_sol) -u = control(direct_sol) -p = costate(direct_sol) +t = time_grid(direct_sol) # the time grid as a vector +x = state(direct_sol) # the state as a function of time +u = control(direct_sol) # the control as a function of time +p = costate(direct_sol) # the costate as a function of time H1 = Lift(F1) # H1(x, p) = p' * F1(x) φ(t) = H1(x(t), p(t)) # switching function @@ -193,9 +189,7 @@ as well as the associated multiplier for the *order one* state constraint on the which is the reason why we use the `@Lie` macro to compute Poisson brackets below. -With the help of the [differential geometry primitives](https://control-toolbox.org/CTBase.jl/stable/api-diffgeom.html) -from [CTBase.jl](https://control-toolbox.org/OptimalControl.jl/stable/api-ctbase.html), -these expressions are straightforwardly translated into Julia code: +With the help of differential geometry primitives, these expressions are straightforwardly translated into Julia code: ```@example main # Controls @@ -284,11 +278,11 @@ We aggregate the data to define the initial guess vector. ### MINPACK.jl -We can use [NonlinearSolve.jl](https://github.com/SciML/NonlinearSolve.jl) package or, instead, the +We can use [NonlinearSolve.jl](https://docs.sciml.ai/NonlinearSolve) package or, instead, the [MINPACK.jl](https://github.com/sglyon/MINPACK.jl) package to solve the shooting equation. To compute the Jacobian of the shooting function we use the -[DifferentiationInterface.jl](https://gdalle.github.io/DifferentiationInterface.jl/DifferentiationInterface) package with -[ForwardDiff.jl](https://github.com/JuliaDiff/ForwardDiff.jl) backend. +[DifferentiationInterface.jl](https://juliadiff.org/DifferentiationInterface.jl/DifferentiationInterface) package with +[ForwardDiff.jl](https://juliadiff.org/ForwardDiff.jl) backend. ```@setup main using NonlinearSolve # interface to NLE solvers diff --git a/docs/src/tutorial-iss.md b/docs/src/tutorial-iss.md index b92fcd3..386db1e 100644 --- a/docs/src/tutorial-iss.md +++ b/docs/src/tutorial-iss.md @@ -3,11 +3,14 @@ In this tutorial we present the indirect simple shooting method on a simple example. Let us start by importing the necessary packages. +We import the [OptimalControl.jl](https://control-toolbox.org/OptimalControl.jl) package to define the optimal control problem. +We import the [Plots.jl](https://docs.juliaplots.org) package to plot the solution. +The [OrdinaryDiffEq.jl](https://docs.sciml.ai/OrdinaryDiffEq) package is used to define the shooting function for the indirect method and the [MINPACK.jl](https://github.com/sglyon/MINPACK.jl) package permits to solve the shooting equation. + ```@example main using OptimalControl # to define the optimal control problem and its flow using OrdinaryDiffEq # to get the Flow function from OptimalControl -using NonlinearSolve # interface to NLE solvers using MINPACK # NLE solver: use to solve the shooting equation using Plots # to plot the solution ``` @@ -154,7 +157,7 @@ nothing # hide ### MINPACK.jl -We can use [NonlinearSolve.jl](https://github.com/SciML/NonlinearSolve.jl) package or, instead, [MINPACK.jl](https://github.com/sglyon/MINPACK.jl) to solve the shooting equation. To compute the Jacobian of the shooting function we use [DifferentiationInterface.jl](https://gdalle.github.io/DifferentiationInterface.jl/DifferentiationInterface) with [ForwardDiff.jl](https://github.com/JuliaDiff/ForwardDiff.jl) backend. +We can use [NonlinearSolve.jl](https://docs.sciml.ai/NonlinearSolve) package or, instead, [MINPACK.jl](https://github.com/sglyon/MINPACK.jl) to solve the shooting equation. To compute the Jacobian of the shooting function we use [DifferentiationInterface.jl](https://juliadiff.org/DifferentiationInterface.jl/DifferentiationInterface) with [ForwardDiff.jl](https://juliadiff.org/ForwardDiff.jl) backend. ```@setup main using MINPACK diff --git a/docs/src/tutorial-lqr-basic.md b/docs/src/tutorial-lqr-basic.md index 048d2c0..c7f3151 100644 --- a/docs/src/tutorial-lqr-basic.md +++ b/docs/src/tutorial-lqr-basic.md @@ -20,7 +20,7 @@ and the initial condition We aim to solve this optimal control problem for different values of $t_f$. First, we need to import the [OptimalControl.jl](https://control-toolbox.org/OptimalControl.jl) package to define the -optimal control problem and [NLPModelsIpopt.jl](jso.dev/NLPModelsIpopt.jl) to solve it. +optimal control problem and [NLPModelsIpopt.jl](https://jso.dev/NLPModelsIpopt.jl) to solve it. We also need to import the [Plots.jl](https://docs.juliaplots.org) package to plot the solution. ```@example main diff --git a/docs/src/tutorial-nlp.md b/docs/src/tutorial-nlp.md index fcbc0df..d9280b9 100644 --- a/docs/src/tutorial-nlp.md +++ b/docs/src/tutorial-nlp.md @@ -7,9 +7,9 @@ CurrentModule = OptimalControl We describe here some more advanced operations related to the discretized optimal control problem. When calling `solve(ocp)` three steps are performed internally: -- first, the OCP is discretized into a DOCP (a nonlinear optimization problem) with [`direct_transcription`](@ref), -- then, this DOCP is solved (with the internal function [`solve_docp`](@ref)), -- finally, a functional solution of the OCP is rebuilt from the solution of the discretized problem, with [`OptimalControlSolution`](@ref). +- first, the OCP is discretized into a DOCP (a nonlinear optimization problem), +- then, this DOCP is solved with a nonlinear programming (NLP) solver, which returns a solution of the discretized problem, +- finally, a functional solution of the OCP is rebuilt from the solution of the discretized problem. These steps can also be done separately, for instance if you want to use your own NLP solver. @@ -55,7 +55,7 @@ We can now use the solver of our choice to solve it. ## Resolution of the NLP problem -For a first example we use the `ipopt` solver from [NLPModelsIpopt.jl](https://github.com/JuliaSmoothOptimizers/NLPModelsIpopt.jl) package to solve the NLP problem. +For a first example we use the `ipopt` solver from [NLPModelsIpopt.jl](https://jso.dev/NLPModelsIpopt.jl) package to solve the NLP problem. ```@example main using NLPModelsIpopt @@ -82,14 +82,14 @@ nlp_sol = madnlp(nlp) ## Initial guess -An initial guess, including warm start, can be passed to [`direct_transcription`](@ref) the same way as for `solve`. +An initial guess, including warm start, can be passed to [`direct_transcription`](https://control-toolbox.org/OptimalControl.jl/stable/dev-ctdirect.html#CTDirect.direct_transcription-Tuple{Model,%20Vararg{Any}}) the same way as for `solve`. ```@example main docp, nlp = direct_transcription(ocp; init=sol) nothing # hide ``` -It can also be changed after the transcription is done, with [`set_initial_guess`](@ref). +It can also be changed after the transcription is done, with [`set_initial_guess`](https://control-toolbox.org/OptimalControl.jl/stable/dev-ctdirect.html#CTDirect.set_initial_guess-Tuple{CTDirect.DOCP,%20Any,%20Any}). ```@example main set_initial_guess(docp, nlp, sol)