Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 6 additions & 4 deletions docs/make.jl
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ cp(
repo_url = "github.com/control-toolbox/OptimalControlProblems.jl"

#
draft = false
draft = true
exclude_from_draft=Symbol[
# :beam
]
Expand All @@ -80,9 +80,11 @@ PROBLEMS_PAGES = generate_documentation_problems(;
makedocs(;
draft=draft, # if draft is true, then the julia code from .md is not executed # debug
# to disable the draft mode in a specific markdown file, use the following:
# ```@meta
# Draft = false
# ```
#=
```@meta
Draft = false
```
=#
#remotes=nothing,
warnonly=:cross_references,
sitename="OptimalControlProblems.jl",
Expand Down
23 changes: 13 additions & 10 deletions docs/problems.jl
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
function generate_documentation(PROBLEM::String; draft::Union{Bool,Nothing})
function generate_documentation(PROBLEM::String, DESCRIPTION::String; draft::Union{Bool,Nothing})
TITLE = uppercasefirst(replace(PROBLEM, "_" => " "))

DRAFT = if isnothing(draft)
Expand All @@ -20,11 +20,11 @@ function generate_documentation(PROBLEM::String; draft::Union{Bool,Nothing})
documentation=DRAFT * """
# $TITLE

We consider the `:$PROBLEM` problem.
$DESCRIPTION

## Packages

First, import all the necessary packages and define the DataFrames to store the data from the model and the resolutions.
Import all necessary packages and define DataFrames to store information about the problem and resolution results.

```@example main
using OptimalControlProblems # to access the Beam model
Expand Down Expand Up @@ -57,7 +57,7 @@ function generate_documentation(PROBLEM::String; draft::Union{Bool,Nothing})

### Solve the problem

Import the problem and solve it.
Import the OptimalControl problem and solve it to obtain the solution.

```@example main
# import model
Expand All @@ -77,7 +77,7 @@ function generate_documentation(PROBLEM::String; draft::Union{Bool,Nothing})
nothing # hide
```

For numerical comparison with the JuMP model resolution, define:
Compute state, control, objective, and iteration data for comparison:

```@example main
t_oc = time_grid(ocp_sol)
Expand Down Expand Up @@ -119,7 +119,7 @@ function generate_documentation(PROBLEM::String; draft::Union{Bool,Nothing})

### Plot the solution

To plot the solution, get the number of states and controls from the metadata:
Visualise states, costates, and controls for the OptimalControl solution:

```@example main
x_vars = OptimalControlProblems.metadata[:$PROBLEM][:state_name]
Expand Down Expand Up @@ -194,7 +194,7 @@ function generate_documentation(PROBLEM::String; draft::Union{Bool,Nothing})

### Plot the solution

Add the state, costate, and control from the JuMP model to the plot:
Overlay the JuMP solution on the previous plots:

```@example main
t = time_grid(:$PROBLEM, model_jp) # t0, ..., tN = tf
Expand All @@ -219,7 +219,7 @@ function generate_documentation(PROBLEM::String; draft::Union{Bool,Nothing})

## Initial guess

The initial guess (or first iterate) is obtained by fixing `max_iter=0` in the solver:
The initial guess can also be visualised by running the solver with `max_iter=0`.

```@raw html
<details><summary>Unfold to see the code for plotting the initial guess.</summary>
Expand Down Expand Up @@ -308,7 +308,7 @@ function generate_documentation(PROBLEM::String; draft::Union{Bool,Nothing})

## Numerical comparison

Next, compare the number of iterations required to obtain the solutions. Also compare the final times, objective values, and the state and costate trajectories in L² norm.
Compare OptimalControl and JuMP solutions in terms of iterations, \$L^2\$ norms, and objective values.

```@raw html
<details><summary>Unfold to get the code of the numerical comparison.</summary>
Expand Down Expand Up @@ -448,9 +448,12 @@ function generate_documentation_problems(;
filename = joinpath(@__DIR__, "src", "problems", string(problem) * ".md")
touch(filename)

# get the description
description = read(joinpath(@__DIR__, "..", "ext", "Descriptions", string(problem) * ".md"), String)

# generate the content
draft_problem = problem ∈ exclude_from_draft ? false : draft
contents = generate_documentation(string(problem); draft=draft_problem)
contents = generate_documentation(string(problem), description; draft=draft_problem)

# write the content in the file
open(filename, "a") do io
Expand Down
2 changes: 1 addition & 1 deletion docs/src/assets/Manifest.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

julia_version = "1.11.6"
manifest_format = "2.0"
project_hash = "474bb317741c3e2578ba5be1b92a71a19071c7b7"
project_hash = "e4420c03c5c208c963d869daa22ca1e9ba918652"

[[deps.ADNLPModels]]
deps = ["ADTypes", "ForwardDiff", "LinearAlgebra", "NLPModels", "Requires", "ReverseDiff", "SparseArrays", "SparseConnectivityTracer", "SparseMatrixColorings"]
Expand Down
18 changes: 12 additions & 6 deletions docs/src/assets/Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,16 @@ Plots = "91a5bcdd-55d7-5caf-9e0b-520d859cae80"
TOML = "fa267f1f-6049-4f14-aa54-33bafae1ed76"

[compat]
Documenter = "1.14"
Ipopt = "1.10"
JuMP = "1.28"
Markdown = "1.11"
CTModels = "0.6"
DataFrames = "1"
Documenter = "1"
DocumenterInterLinks = "1"
ExaModels = "0.9"
Ipopt = "1"
JuMP = "1"
Markdown = "1"
NLPModels = "0.21"
NLPModelsIpopt = "0.10"
OptimalControl = "1.1"
TOML = "1.0"
OptimalControl = "1"
Plots = "1"
TOML = "1"
47 changes: 47 additions & 0 deletions ext/Descriptions/beam.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
The *beam problem* is a classical benchmark in constrained optimal control. It originates from the Euler–Bernoulli beam model (see Bryson et al. 1963). The system describes the deflection of a clamped flexible beam under an external force. Both the state trajectory $x(\cdot)$ and the control $u(\cdot)$ are decision variables. The aim is to minimise the control effort subject to boundary conditions and a state inequality constraint on the displacement.

The problem can be written as

```math
\min_{x,\,u} J(x,u) = \int_0^1 u(t)^2 \, dt
```

subject to the dynamics
```math
\dot{x}_1(t) = x_2(t), \qquad
\dot{x}_2(t) = u(t),
```

with boundary conditions
```math
x_1(0) = 0, \quad x_1(1) = 0, \qquad
x_2(0) = 1, \quad x_2(1) = -1,
```

and the constraints
```math
-10 \le u(t) \le 5, \qquad
0 \le x_1(t) \le a,
```

where $a$ denotes the maximal admissible deflection (e.g. $a=0.1$ in the current implementation).

### Qualitative behaviour

- If $a \geq 1/4$, the inequality constraint is inactive and the solution is $x(t) = t(1-t)$.
- If $a \in [1/6, 1/4]$, there is a single touch point at $t=1/2$.
- If $a < 1/6$, a boundary arc appears, with the constraint active on an interval.

These features illustrate the role of state inequality constraints in shaping optimal trajectories and controls.

### Characteristics

- Linear–quadratic dynamics and cost.
- Asymmetric control bounds.
- State inequality constraint induces touch points or boundary arcs depending on $a$.
- Widely used as a benchmark in numerical optimal control libraries.

### References

- Bryson, A.E., Denham, W.F., & Dreyfus, S.E. (1963). *Optimal programming problems with inequality constraints I: necessary conditions for extremal solutions*. AIAA Journal.
- BOCOP examples: Clamped Beam problem. [Examples-BOCOP.pdf](https://project.inria.fr/bocop/files/2017/05/Examples-BOCOP.pdf)
51 changes: 51 additions & 0 deletions ext/Descriptions/bioreactor.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
This problem models a coupled photobioreactor–digester system for methane production.
The system consists of three state variables: the algae concentration $y(t)$, the substrate concentration $s(t)$, and the biomass concentration $b(t)$.
The control variable $u(t)$ represents the input flow rate between the two units.
The dynamics include algal growth driven by light, substrate consumption, and biomass evolution.
The aim is to maximise methane production over a fixed time horizon under biological and operational constraints.

### Problem formulation

We minimise

```math
\min_{y,\,s,\,b,\,u} J(y,s,b,u) = - \frac{1}{\beta+c} \int_0^T \mu_2(s(t))\, b(t)\, dt,
```

subject to the dynamics
```math
\dot{y}(t) = \frac{\mu(t)\, y(t)}{1+y(t)} - (r+u(t))\, y(t),
```
```math
\dot{s}(t) = -\mu_2(s(t))\, b(t) + u(t)\, \beta\big(\gamma y(t) - s(t)\big),
```
```math
\dot{b}(t) = \big(\mu_2(s(t)) - u(t)\, \beta\big)\, b(t),
```

with
- **Light model:** $\mu(t) = \mu_{\text{bar}} \,\max(0,\sin(\tau(t)))^2$, where $\tau(t)$ encodes a periodic day–night cycle,
- **Growth function (Monod law):** $\mu_2(s) = \mu_2^m \,\dfrac{s}{K_s + s}$.

### Constraints

- Control bounds: $0 \leq u(t) \leq 1$,
- State bounds: $y(t) \geq 0,\; s(t) \geq 0,\; b(t) \geq 10^{-3}$,
- Initial conditions: $0.05 \leq y(0) \leq 0.25$, $0.5 \leq s(0) \leq 5$, $0.5 \leq b(0) \leq 3$.

The horizon is fixed to $T = 200$ (rescaled units), corresponding to several day–night periods.

### Qualitative behaviour

The optimal solution exploits the periodic structure of the problem:
during illuminated phases, algal growth is favoured, while in dark phases methane production becomes predominant.
The control exhibits a near bang–bang structure, alternating between minimal and maximal input flows, with possible singular arcs when substrate and biomass reach balanced levels.
The constraints on positivity of the states are typically active for $b(t)$ at the beginning of the process.

### References

- Bayen, T., Mairet, F., Martinon, P., & Sebbah, M. (2014). *Analysis of a periodic optimal control problem connected to microalgae anaerobic digestion*. Optimal Control Applications and Methods. [DOI:10.1002/oca.2127](https://hal.archives-ouvertes.fr/hal-00860570)
- Bayen, T., Mairet, F., Martinon, P., & Sebbah, M. (2013). *Optimising the anaerobic digestion of microalgae in a coupled process*. 13th European Control Conference.
- Barbosa, M.J., & Wijffels, R.H. (2010). *An Outlook on Microalgal Biofuels*. Science, 329, 796–799.
- Betts, J.T. (2001). *Practical methods for optimal control using nonlinear programming*. SIAM.
- BOCOP repository: https://github.com/control-toolbox/bocop/tree/main/bocop
98 changes: 98 additions & 0 deletions ext/Descriptions/cart_pendulum.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
This problem involves swinging up a pendulum mounted on a cart, a classical **underactuated system**.
The goal is to move the pendulum from its downward equilibrium to the upright position while controlling the horizontal motion of the cart, in **minimum time**.

### System Dynamics

The system has four states and one control:

- $x$ : cart position
- $v$ : cart velocity
- $\theta$ : pendulum angle from downward vertical
- $\omega$ : pendulum angular velocity
- $F_{\rm ex}$ : horizontal force applied to the cart (control)

The dynamics are expressed as

```math
\dot{x} = v
```

```math
\dot{v} = -\frac{1}{J} \, c
```

```math
\dot{\theta} = \omega
```

```math
\dot{\omega} = \alpha(\dot{v})
```

where

```math
\alpha(ddx) = \frac{0.5 \, L \, m}{I + 0.25 \, m L^2} \big(-ddx \cos\theta - g \sin\theta\big)
```

```math
\text{ddCOG} = L \, \omega \, [-\sin\theta, \cos\theta] + \frac{L}{2} \,[\cos\theta, \sin\theta] \, \alpha(ddx) + [ddx,0]
```

```math
\text{FXFY} = m \, \text{ddCOG} + [0, m g]
```

```math
c = -\text{FXFY}_x + F_{\rm ex} - m_{\rm cart} ddx - J ddx
```

Here, $J$ represents the effective mass of the cart, $m$ and $m_{\rm cart}$ are the pendulum and cart masses, $L$ is the pendulum length, and $I$ its moment of inertia. The variable $ddx$ is an auxiliary variable related to the cart acceleration used for the dynamics formulation.

### Boundary Conditions

- **Initial conditions**:

```math
x(0) = 0, \quad \theta(0) = 0, \quad \omega(0) = 0
```

- **Final conditions**:

```math
\theta(T) = \pi, \quad \omega(T) = 0
```

- Cart position and velocity constraints:

```math
|x(t)| \le 1, \quad |v(t)| \le 2
```

- Control limits:

```math
|F_{\rm ex}(t)| \le 5
```

- Time horizon:

```math
T \ge 0.1
```

### Objective

The goal is to **minimize the final time** $T$:

```math
J = T \to \min
```

subject to the dynamics, boundary conditions, and state/control constraints.

### References

- Vanroye, L., Sathya, A., De Schutter, J., & Decré, W. (2023). FATROP: A Fast Constrained Optimal Control Problem Solver for Robot Trajectory Optimization and Control. *arXiv preprint arXiv:2303.16746*. Retrieved from https://arxiv.org/pdf/2303.16746
- Åström, K. J., & Furuta, K. (2000). Swinging up a pendulum by energy control. *Automatica*, 36(2), 287–295.
- Lipp, T., & Boyd, S. (2014). Variations and extensions of the cart-pole swing-up problem. *Stanford University Technical Report*.
Loading
Loading