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
2 changes: 2 additions & 0 deletions Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ version = "0.2.1"

[deps]
CTBase = "54762871-cc72-4466-b8e8-f6c8b58076cd"
CTDirect = "790bbbee-bee9-49ee-8912-a9de031322d5"
CTModels = "34c4fa32-2049-4079-8329-de33c2a22e2d"
DocStringExtensions = "ffbed154-4ef7-542d-bbb7-c09d3a79fcae"
ExaModels = "1037b233-b668-4ce9-9b63-f9f681f55dd2"
Expand All @@ -20,6 +21,7 @@ OptimalControlModels = "OptimalControl"

[compat]
CTBase = "0.16"
CTDirect = "0.16"
CTModels = "0.6"
DocStringExtensions = "0.9"
ExaModels = "0.9"
Expand Down
2 changes: 1 addition & 1 deletion 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 = true
draft = false
exclude_from_draft=Symbol[
# :beam
]
Expand Down
82 changes: 42 additions & 40 deletions docs/problems.jl
Original file line number Diff line number Diff line change
Expand Up @@ -63,11 +63,12 @@ function generate_documentation(

```@example main
# import model
docp, model_oc = $PROBLEM(OptimalControlBackend())
docp = $PROBLEM(OptimalControlBackend())
nlp_oc = nlp_model(docp)

# solve
nlp_sol = NLPModelsIpopt.ipopt(
model_oc;
nlp_oc;
print_level=4,
tol=1e-8,
mu_strategy="adaptive",
Expand Down Expand Up @@ -100,8 +101,8 @@ function generate_documentation(
(
Problem=:$PROBLEM,
Grid_Size=OptimalControlProblems.metadata[:$PROBLEM][:N],
Variables=get_nvar(model_oc),
Constraints=get_ncon(model_oc),
Variables=get_nvar(nlp_oc),
Constraints=get_ncon(nlp_oc),
)
)
```
Expand Down Expand Up @@ -155,27 +156,27 @@ function generate_documentation(

```@example main
# import model
model_jp = $PROBLEM(JuMPBackend())
nlp_jp = $PROBLEM(JuMPBackend())

# solve
set_optimizer(model_jp, Ipopt.Optimizer)
set_optimizer_attribute(model_jp, "print_level", 4)
set_optimizer_attribute(model_jp, "tol", 1e-8)
set_optimizer_attribute(model_jp, "mu_strategy", "adaptive")
set_optimizer_attribute(model_jp, "linear_solver", "mumps")
set_optimizer_attribute(model_jp, "sb", "yes")
optimize!(model_jp)
set_optimizer(nlp_jp, Ipopt.Optimizer)
set_optimizer_attribute(nlp_jp, "print_level", 4)
set_optimizer_attribute(nlp_jp, "tol", 1e-8)
set_optimizer_attribute(nlp_jp, "mu_strategy", "adaptive")
set_optimizer_attribute(nlp_jp, "linear_solver", "mumps")
set_optimizer_attribute(nlp_jp, "sb", "yes")
optimize!(nlp_jp)
```

For the numerical comparison, define:

```@example main
t_jp = time_grid(:$PROBLEM, model_jp)
x_jp = state(:$PROBLEM, model_jp).(t_jp)
u_jp = control(:$PROBLEM, model_jp).(t_jp)
o_jp = objective_value(model_jp)
v_jp = variable(:$PROBLEM, model_jp)
i_jp = barrier_iterations(model_jp)
t_jp = time_grid(:$PROBLEM, nlp_jp)
x_jp = state(:$PROBLEM, nlp_jp).(t_jp)
u_jp = control(:$PROBLEM, nlp_jp).(t_jp)
o_jp = objective_value(nlp_jp)
v_jp = variable(:$PROBLEM, nlp_jp)
i_jp = barrier_iterations(nlp_jp)
nothing # hide
```

Expand All @@ -187,9 +188,9 @@ function generate_documentation(
push!(data_re,
(
Model=:JuMP,
Flag=termination_status(model_jp),
Iterations=barrier_iterations(model_jp),
Objective=objective_value(model_jp),
Flag=termination_status(nlp_jp),
Iterations=barrier_iterations(nlp_jp),
Objective=objective_value(nlp_jp),
)
)
```
Expand All @@ -199,10 +200,10 @@ function generate_documentation(
Overlay the JuMP solution on the previous plots:

```@example main
t = time_grid(:$PROBLEM, model_jp) # t0, ..., tN = tf
x = state(:$PROBLEM, model_jp) # function of time
u = control(:$PROBLEM, model_jp) # function of time
p = costate(:$PROBLEM, model_jp) # function of time
t = time_grid(:$PROBLEM, nlp_jp) # t0, ..., tN = tf
x = state(:$PROBLEM, nlp_jp) # function of time
u = control(:$PROBLEM, nlp_jp) # function of time
p = costate(:$PROBLEM, nlp_jp) # function of time

for i in 1:n # state
label = i == 1 ? "JuMP" : :none
Expand Down Expand Up @@ -231,11 +232,12 @@ function generate_documentation(
function plot_initial_guess()

# import OptimalControl model
docp, model_oc = $PROBLEM(OptimalControlBackend())
docp = $PROBLEM(OptimalControlBackend())
nlp_oc = nlp_model(docp)

# solve
nlp_sol = NLPModelsIpopt.ipopt(
model_oc;
nlp_oc;
max_iter=0,
print_level=5,
tol=1e-8,
Expand Down Expand Up @@ -263,23 +265,23 @@ function generate_documentation(
end

# import JuMP model
model_jp = $PROBLEM(JuMPBackend())
nlp_jp = $PROBLEM(JuMPBackend())

# solve
set_optimizer(model_jp, Ipopt.Optimizer)
set_optimizer_attribute(model_jp, "max_iter", 0)
set_optimizer_attribute(model_jp, "print_level", 5)
set_optimizer_attribute(model_jp, "tol", 1e-8)
set_optimizer_attribute(model_jp, "mu_strategy", "adaptive")
set_optimizer_attribute(model_jp, "linear_solver", "mumps")
set_optimizer_attribute(model_jp, "sb", "yes")
optimize!(model_jp)
set_optimizer(nlp_jp, Ipopt.Optimizer)
set_optimizer_attribute(nlp_jp, "max_iter", 0)
set_optimizer_attribute(nlp_jp, "print_level", 5)
set_optimizer_attribute(nlp_jp, "tol", 1e-8)
set_optimizer_attribute(nlp_jp, "mu_strategy", "adaptive")
set_optimizer_attribute(nlp_jp, "linear_solver", "mumps")
set_optimizer_attribute(nlp_jp, "sb", "yes")
optimize!(nlp_jp)

# plot
t = time_grid(:$PROBLEM, model_jp) # t0, ..., tN = tf
x = state(:$PROBLEM, model_jp) # function of time
u = control(:$PROBLEM, model_jp) # function of time
p = costate(:$PROBLEM, model_jp) # function of time
t = time_grid(:$PROBLEM, nlp_jp) # t0, ..., tN = tf
x = state(:$PROBLEM, nlp_jp) # function of time
u = control(:$PROBLEM, nlp_jp) # function of time
p = costate(:$PROBLEM, nlp_jp) # function of time

for i in 1:n # state
label = i == 1 ? "JuMP" : :none
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 @@ -1042,7 +1042,7 @@ uuid = "5f98b655-cc9a-415a-b60e-744165666948"
version = "1.1.1"

[[deps.OptimalControlProblems]]
deps = ["CTBase", "CTModels", "DocStringExtensions", "ExaModels", "OrderedCollections"]
deps = ["CTBase", "CTDirect", "CTModels", "DocStringExtensions", "ExaModels", "OrderedCollections"]
path = "/Users/ocots/Research/logiciels/dev/control-toolbox/OptimalControlProblems"
uuid = "59046045-fb9c-4c23-964f-ff0a25704f96"
version = "0.2.1"
Expand Down
8 changes: 4 additions & 4 deletions docs/src/dev-add.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,9 @@ function OptimalControlProblems.new_problem(::OptimalControlBackend; N::Int=step
init = ()

# DOCP and NLP
docp, nlp = direct_transcription(ocp; init=init, grid_size=N, disc_method=:trapeze)
docp = direct_transcription(ocp; init=init, grid_size=N, disc_method=:trapeze)

return docp, nlp
return docp

end
```
Expand All @@ -61,11 +61,11 @@ function OptimalControlProblems.new_problem(::JuMPBackend; N::Int=steps_number_d
tf = final_time_data(:new_problem)

# model
model = JuMP.Model()
nlp = JuMP.Model()

# Define the problem here
# ...

return model
return nlp
end
```
9 changes: 5 additions & 4 deletions docs/src/problems-introduction.md
Original file line number Diff line number Diff line change
Expand Up @@ -136,8 +136,9 @@ data_nlp = DataFrame( # to store data of the NLPs
for problem in problems()

#
docp, model = eval(problem)(OptimalControlBackend())
ocp = docp.ocp
docp = eval(problem)(OptimalControlBackend())
nlp = nlp_model(docp)
ocp = ocp_model(docp)

#
cost = if has_mayer_cost(ocp) && has_lagrange_cost(ocp)
Expand Down Expand Up @@ -188,8 +189,8 @@ for problem in problems()
(
Problem=problem,
Steps=N,
Variables=get_nvar(model),
Constraints=get_ncon(model),
Variables=get_nvar(nlp),
Constraints=get_ncon(nlp),
)
)
end
Expand Down
42 changes: 24 additions & 18 deletions docs/src/tutorial-get.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ Each problem in the **OptimalControlProblems** package is modelled both in JuMP

## Get an OptimalControl model

### NLP Model
### DOCP and NLP Model

To get an OptimalControl model, first install [OptimalControl](https://control-toolbox.org/OptimalControl.jl/stable/#Installation) and import the packages:

Expand All @@ -16,44 +16,48 @@ using OptimalControlProblems
Then, to obtain the OptimalControl model of the beam problem, run:

```@example main_oc
_, model = beam(OptimalControlBackend())
model # hide
docp = beam(OptimalControlBackend())
nlp = nlp_model(docp)
```

The model represents the nonlinear programming problem (NLP) obtained after discretising the optimal control problem (OCP). See the [Introduction](@ref problems-introduction) page for details. The model is an [`ADNLPModels.ADNLPModel`](@extref), which provides automatic differentiation (AD)-based models that follow the [NLPModels.jl](https://github.com/JuliaSmoothOptimizers/NLPModels.jl) API.
The `nlp` model represents the nonlinear programming problem (NLP) obtained after discretising the optimal control problem (OCP). See the [Introduction](@ref problems-introduction) page for details. The model is an [`ADNLPModels.ADNLPModel`](@extref), which provides automatic differentiation (AD)-based models that follow the [NLPModels.jl](https://github.com/JuliaSmoothOptimizers/NLPModels.jl) API.

### DOCP
!!! note

You also have access to the DOCP model, which corresponds to the discretised optimal control problem. Roughly speaking, the DOCP model is the union of the NLP and OCP models. For more details, see this [tutorial](@extref Tutorials Discretization-and-NLP-problem) or the documentation of [`CTDirect.DOCP`](@extref).

### OCP

You also have access to the DOCP model, which corresponds to the discretised optimal control problem. For more details, see this [tutorial](@extref Tutorials Discretization-and-NLP-problem) or the documentation of [`CTDirect.DOCP`](@extref).
You also have access to the OCP model, which corresponds to the optimal control problem.

```@example main_oc
docp, model = beam(OptimalControlBackend())
ocp = ocp_model(docp)
nothing # hide
```

### Number of variables, constraints, and nonzeros

The model follows the [NLPModels.jl](https://github.com/JuliaSmoothOptimizers/NLPModels.jl) API. See the existing [Attributes](https://jso.dev/NLPModels.jl/stable/#Attributes) and the available getter functions (`get_X`) [here](https://jso.dev/NLPModels.jl/stable/reference).
The `nlp` model follows the [NLPModels.jl](https://github.com/JuliaSmoothOptimizers/NLPModels.jl) API. See the existing [Attributes](https://jso.dev/NLPModels.jl/stable/#Attributes) and the available getter functions (`get_X`) [here](https://jso.dev/NLPModels.jl/stable/reference).

To get the number of variables:

```@example main_oc
using NLPModels
get_nvar(model)
get_nvar(nlp)
```

To get the number of constraints:

```@example main_oc
get_ncon(model)
get_ncon(nlp)
```

To get the number of nonzeros:

```@example main_oc
nnzo = get_nnzo(model) # Gradient of the objective
nnzj = get_nnzj(model) # Jacobian of the constraints
nnzh = get_nnzh(model) # Hessian of the Lagrangian
nnzo = get_nnzo(nlp) # Gradient of the objective
nnzj = get_nnzj(nlp) # Jacobian of the constraints
nnzh = get_nnzh(nlp) # Hessian of the Lagrangian

println("nnzo = ", nnzo)
println("nnzj = ", nnzj)
Expand All @@ -77,13 +81,15 @@ OptimalControlProblems.metadata[:beam][:N]
Each problem can be parameterised by the number of steps:

```@example main_oc
docp, model = beam(OptimalControlBackend(); N=100)
get_nvar(model)
docp = beam(OptimalControlBackend(); N=100)
nlp = nlp_model(docp)
get_nvar(nlp)
```

```@example main_oc
docp, model = beam(OptimalControlBackend(); N=200)
get_nvar(model)
docp = beam(OptimalControlBackend(); N=200)
nlp = nlp_model(docp)
get_nvar(nlp)
```

## Get a JuMP model
Expand All @@ -98,7 +104,7 @@ using OptimalControlProblems
Then, to obtain the JuMP model of the beam problem, run:

```@example main_jp
model = beam(JuMPBackend())
nlp = beam(JuMPBackend())
```

!!! note
Expand Down
Loading
Loading