From 8b77906b93c29b44e2f35dea8a3bbe111f3afedc Mon Sep 17 00:00:00 2001 From: HediChennoufi Date: Wed, 14 Jan 2026 19:13:32 +0100 Subject: [PATCH 01/24] test new inits --- ext/OptimalControlModels/robot.jl | 2 +- ext/OptimalControlModels/space_shuttle.jl | 2 +- ext/OptimalControlModels/steering.jl | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/ext/OptimalControlModels/robot.jl b/ext/OptimalControlModels/robot.jl index 1bfe831a..72859325 100644 --- a/ext/OptimalControlModels/robot.jl +++ b/ext/OptimalControlModels/robot.jl @@ -117,7 +117,7 @@ function OptimalControlProblems.robot( end # initial guess - tf = 1 + tf = 9.1 xinit = t -> [ ρ_t0, diff --git a/ext/OptimalControlModels/space_shuttle.jl b/ext/OptimalControlModels/space_shuttle.jl index 2d6e6d25..c080a1bf 100644 --- a/ext/OptimalControlModels/space_shuttle.jl +++ b/ext/OptimalControlModels/space_shuttle.jl @@ -175,7 +175,7 @@ function OptimalControlProblems.space_shuttle( # initial guess: linear interpolation for h, v, gamma (NB. t0 = 0), constant for the rest # variable time step seems to be initialized at 1 in jump # note that ipopt will project the initial guess inside the bounds anyway. - tf_init = (tf_l+tf_u)/2 + tf_init = 2000.0 x_init = t -> [ h_t0 + (t - t0) / (tf_init - t0) * (h_tf - h_t0), diff --git a/ext/OptimalControlModels/steering.jl b/ext/OptimalControlModels/steering.jl index 36aeabff..a1539e56 100644 --- a/ext/OptimalControlModels/steering.jl +++ b/ext/OptimalControlModels/steering.jl @@ -85,7 +85,7 @@ function OptimalControlProblems.steering( end end xinit = t -> [gen_x0(t, i) for i in 1:4] - init = (state=xinit, control=0, variable=1) + init = (state=xinit, control=0, variable=0.6) # discretise the optimal control problem docp = direct_transcription( From 7c85b59422a0aa9629e0c31b4b24905ea5a5dfde Mon Sep 17 00:00:00 2001 From: HediChennoufi Date: Wed, 21 Jan 2026 22:10:43 +0100 Subject: [PATCH 02/24] test2 inits sshuttle steering robot glider --- ext/JuMPModels/glider.jl | 2 +- ext/JuMPModels/robot.jl | 2 +- ext/JuMPModels/space_shuttle.jl | 2 +- ext/JuMPModels/steering.jl | 2 +- ext/OptimalControlModels/glider.jl | 13 ++++++++----- ext/OptimalControlModels/space_shuttle.jl | 2 +- ext/OptimalControlModels_s/glider_s.jl | 12 ++++++++---- ext/OptimalControlModels_s/robot_s.jl | 2 +- ext/OptimalControlModels_s/space_shuttle_s.jl | 2 +- ext/OptimalControlModels_s/steering_s.jl | 2 +- 10 files changed, 24 insertions(+), 17 deletions(-) diff --git a/ext/JuMPModels/glider.jl b/ext/JuMPModels/glider.jl index 164600a7..c4b9bab5 100644 --- a/ext/JuMPModels/glider.jl +++ b/ext/JuMPModels/glider.jl @@ -76,7 +76,7 @@ function OptimalControlProblems.glider( @variables( model, begin - tf ≥ tf_l, (start = 1) + tf ≥ tf_l, (start = 60) x[k = 0:N] ≥ x_l, (start = x_t0 + vx_t0 * k / N) y[k = 0:N], (start = y_t0 + (k / N) * (y_tf - y_t0)) vx[k = 0:N] ≥ vx_l, (start = vx_t0) diff --git a/ext/JuMPModels/robot.jl b/ext/JuMPModels/robot.jl index 79bfadc0..a77ffe80 100644 --- a/ext/JuMPModels/robot.jl +++ b/ext/JuMPModels/robot.jl @@ -104,7 +104,7 @@ function OptimalControlProblems.robot( uθ_l ≤ uθ[0:N] ≤ uθ_u, (start = 0) uϕ_l ≤ uϕ[0:N] ≤ uϕ_u, (start = 0) - tf ≥ tf_l, (start = 1) + tf ≥ tf_l, (start = 9.1) end ) diff --git a/ext/JuMPModels/space_shuttle.jl b/ext/JuMPModels/space_shuttle.jl index 0479eebf..17a16cd5 100644 --- a/ext/JuMPModels/space_shuttle.jl +++ b/ext/JuMPModels/space_shuttle.jl @@ -184,7 +184,7 @@ function OptimalControlProblems.space_shuttle( set_start_value.(model[:ψ], vec(initial_guess[:, 6])) set_start_value.(model[:α], vec(initial_guess[:, 7])) set_start_value.(model[:β], vec(initial_guess[:, 8])) - set_start_value.(model[:tf], (tf_l+tf_u)/2) + set_start_value.(model[:tf], 0.5) ####### # Functions to restore `h` and `v` to their true scale @expression(model, h[j = 0:N], scaled_h[j] * scaling_h) diff --git a/ext/JuMPModels/steering.jl b/ext/JuMPModels/steering.jl index cd40af69..8554cc42 100644 --- a/ext/JuMPModels/steering.jl +++ b/ext/JuMPModels/steering.jl @@ -51,7 +51,7 @@ function OptimalControlProblems.steering( x₄_tf = params[:x₄_tf] # - tf_start = 1 + tf_start = 0.6 function gen_x0(k, i) if i == 1 || i == 4 return 0.0 diff --git a/ext/OptimalControlModels/glider.jl b/ext/OptimalControlModels/glider.jl index d91059be..c0836c2f 100644 --- a/ext/OptimalControlModels/glider.jl +++ b/ext/OptimalControlModels/glider.jl @@ -110,11 +110,14 @@ function OptimalControlProblems.glider( end # initial guess - tfinit = 1 - xinit = - t -> [x_t0 + vx_t0 * t / tfinit, y_t0 + t / tfinit * (y_tf - y_t0), vx_t0, vy_t0] - uinit = cL_max / 2 - init = (state=xinit, control=uinit, variable=tfinit) + tfinit = 60.0 + xinit = t -> [ + x_t0 + vx_t0 * t, + y_t0 + (t / tfinit) * (y_tf - y_t0), + vx_t0 + (t / tfinit) * (vx_tf - vx_t0), + vy_t0 + (t / tfinit) * (vy_tf - vy_t0) + ] + uinit = (cL_min + cL_max) / 2 # discretise the optimal control problem docp = direct_transcription( diff --git a/ext/OptimalControlModels/space_shuttle.jl b/ext/OptimalControlModels/space_shuttle.jl index c080a1bf..08bcb59b 100644 --- a/ext/OptimalControlModels/space_shuttle.jl +++ b/ext/OptimalControlModels/space_shuttle.jl @@ -175,7 +175,7 @@ function OptimalControlProblems.space_shuttle( # initial guess: linear interpolation for h, v, gamma (NB. t0 = 0), constant for the rest # variable time step seems to be initialized at 1 in jump # note that ipopt will project the initial guess inside the bounds anyway. - tf_init = 2000.0 + tf_init = 0.5 x_init = t -> [ h_t0 + (t - t0) / (tf_init - t0) * (h_tf - h_t0), diff --git a/ext/OptimalControlModels_s/glider_s.jl b/ext/OptimalControlModels_s/glider_s.jl index 59cd87e7..159a0a0d 100644 --- a/ext/OptimalControlModels_s/glider_s.jl +++ b/ext/OptimalControlModels_s/glider_s.jl @@ -104,10 +104,14 @@ function OptimalControlProblems.glider_s( end # initial guess - tfinit = 1 - xinit = - t -> [x_t0 + vx_t0 * t / tfinit, y_t0 + t / tfinit * (y_tf - y_t0), vx_t0, vy_t0] - uinit = cL_max / 2 + tfinit = 60.0 + xinit = t -> [ + x_t0 + vx_t0 * t, + y_t0 + (t / tfinit) * (y_tf - y_t0), + vx_t0 + (t / tfinit) * (vx_tf - vx_t0), + vy_t0 + (t / tfinit) * (vy_tf - vy_t0) + ] + uinit = (cL_min + cL_max) / 2 init = (state=xinit, control=uinit, variable=tfinit) # discretise the optimal control problem diff --git a/ext/OptimalControlModels_s/robot_s.jl b/ext/OptimalControlModels_s/robot_s.jl index 2756c18b..c7b2fbda 100644 --- a/ext/OptimalControlModels_s/robot_s.jl +++ b/ext/OptimalControlModels_s/robot_s.jl @@ -122,7 +122,7 @@ function OptimalControlProblems.robot_s( end # initial guess - tf = 1 + tf = 9.1 xinit = t -> [ ρ_t0, diff --git a/ext/OptimalControlModels_s/space_shuttle_s.jl b/ext/OptimalControlModels_s/space_shuttle_s.jl index f1469e0a..14951a91 100644 --- a/ext/OptimalControlModels_s/space_shuttle_s.jl +++ b/ext/OptimalControlModels_s/space_shuttle_s.jl @@ -164,7 +164,7 @@ function OptimalControlProblems.space_shuttle_s( # initial guess: linear interpolation for h, v, gamma (NB. t0 = 0), constant for the rest # variable time step seems to be initialized at 1 in jump # note that ipopt will project the initial guess inside the bounds anyway. - tf_init = (tf_l+tf_u)/2 + tf_init = 0.5 x_init = t -> [ h_t0 + (t - t0) / (tf_init - t0) * (h_tf - h_t0), diff --git a/ext/OptimalControlModels_s/steering_s.jl b/ext/OptimalControlModels_s/steering_s.jl index c78da787..047c2efe 100644 --- a/ext/OptimalControlModels_s/steering_s.jl +++ b/ext/OptimalControlModels_s/steering_s.jl @@ -85,7 +85,7 @@ function OptimalControlProblems.steering_s( end end xinit = t -> [gen_x0(t, i) for i in 1:4] - init = (state=xinit, control=0, variable=1) + init = (state=xinit, control=0, variable=0.6) # discretise the optimal control problem docp = direct_transcription( From a9c5670050bdcbc9c5e7debb4b4fd58e3ed06b43 Mon Sep 17 00:00:00 2001 From: HediChennoufi Date: Wed, 21 Jan 2026 22:23:07 +0100 Subject: [PATCH 03/24] modif --- ext/OptimalControlModels/glider.jl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ext/OptimalControlModels/glider.jl b/ext/OptimalControlModels/glider.jl index c0836c2f..592d5591 100644 --- a/ext/OptimalControlModels/glider.jl +++ b/ext/OptimalControlModels/glider.jl @@ -117,7 +117,8 @@ function OptimalControlProblems.glider( vx_t0 + (t / tfinit) * (vx_tf - vx_t0), vy_t0 + (t / tfinit) * (vy_tf - vy_t0) ] - uinit = (cL_min + cL_max) / 2 + uinit = (cL_min + cL_max) / 2 + init = (state=xinit, control=uinit, variable=tfinit) # discretise the optimal control problem docp = direct_transcription( From 577db745340c704dc13ef85caf2ce86d647c883a Mon Sep 17 00:00:00 2001 From: HediChennoufi Date: Wed, 28 Jan 2026 22:41:35 +0100 Subject: [PATCH 04/24] modif inits spaceshuttle glider --- ext/JuMPModels/glider.jl | 6 +++--- ext/JuMPModels/space_shuttle.jl | 2 +- ext/OptimalControlModels/glider.jl | 6 +++--- ext/OptimalControlModels/space_shuttle.jl | 6 +++--- ext/OptimalControlModels_s/glider_s.jl | 6 +++--- ext/OptimalControlModels_s/space_shuttle_s.jl | 6 +++--- 6 files changed, 16 insertions(+), 16 deletions(-) diff --git a/ext/JuMPModels/glider.jl b/ext/JuMPModels/glider.jl index c4b9bab5..52331893 100644 --- a/ext/JuMPModels/glider.jl +++ b/ext/JuMPModels/glider.jl @@ -76,12 +76,12 @@ function OptimalControlProblems.glider( @variables( model, begin - tf ≥ tf_l, (start = 60) - x[k = 0:N] ≥ x_l, (start = x_t0 + vx_t0 * k / N) + tf ≥ tf_l, (start = 100.0) #### + x[k = 0:N] ≥ x_l, (start = x_t0 + (k / N) * 1248.0) #### y[k = 0:N], (start = y_t0 + (k / N) * (y_tf - y_t0)) vx[k = 0:N] ≥ vx_l, (start = vx_t0) vy[k = 0:N], (start = vy_t0) - cL_min ≤ cL[k = 0:N] ≤ cL_max, (start = cL_max / 2) + cL_min ≤ cL[k = 0:N] ≤ cL_max, (start = 1.0) #### end ) diff --git a/ext/JuMPModels/space_shuttle.jl b/ext/JuMPModels/space_shuttle.jl index 17a16cd5..42d50df7 100644 --- a/ext/JuMPModels/space_shuttle.jl +++ b/ext/JuMPModels/space_shuttle.jl @@ -184,7 +184,7 @@ function OptimalControlProblems.space_shuttle( set_start_value.(model[:ψ], vec(initial_guess[:, 6])) set_start_value.(model[:α], vec(initial_guess[:, 7])) set_start_value.(model[:β], vec(initial_guess[:, 8])) - set_start_value.(model[:tf], 0.5) ####### + set_start_value.(model[:tf], 2000.0) ####### # Functions to restore `h` and `v` to their true scale @expression(model, h[j = 0:N], scaled_h[j] * scaling_h) diff --git a/ext/OptimalControlModels/glider.jl b/ext/OptimalControlModels/glider.jl index 592d5591..cbec4a64 100644 --- a/ext/OptimalControlModels/glider.jl +++ b/ext/OptimalControlModels/glider.jl @@ -110,14 +110,14 @@ function OptimalControlProblems.glider( end # initial guess - tfinit = 60.0 + tfinit = 100.0 xinit = t -> [ - x_t0 + vx_t0 * t, + x_t0 + (t / tfinit) * 1248.0, y_t0 + (t / tfinit) * (y_tf - y_t0), vx_t0 + (t / tfinit) * (vx_tf - vx_t0), vy_t0 + (t / tfinit) * (vy_tf - vy_t0) ] - uinit = (cL_min + cL_max) / 2 + uinit = 1.0 init = (state=xinit, control=uinit, variable=tfinit) # discretise the optimal control problem diff --git a/ext/OptimalControlModels/space_shuttle.jl b/ext/OptimalControlModels/space_shuttle.jl index 08bcb59b..bdccc605 100644 --- a/ext/OptimalControlModels/space_shuttle.jl +++ b/ext/OptimalControlModels/space_shuttle.jl @@ -56,8 +56,8 @@ function OptimalControlProblems.space_shuttle( # Δt_min = params[:Δt_min] Δt_max = params[:Δt_max] - tf_l = grid_size*Δt_min - tf_u = grid_size*Δt_max + tf_l = 1500.0 # + tf_u = 2500.0 # ## Initial conditions h_t0 = params[:h_t0] @@ -175,7 +175,7 @@ function OptimalControlProblems.space_shuttle( # initial guess: linear interpolation for h, v, gamma (NB. t0 = 0), constant for the rest # variable time step seems to be initialized at 1 in jump # note that ipopt will project the initial guess inside the bounds anyway. - tf_init = 0.5 + tf_init = 2000 x_init = t -> [ h_t0 + (t - t0) / (tf_init - t0) * (h_tf - h_t0), diff --git a/ext/OptimalControlModels_s/glider_s.jl b/ext/OptimalControlModels_s/glider_s.jl index 159a0a0d..7e73c295 100644 --- a/ext/OptimalControlModels_s/glider_s.jl +++ b/ext/OptimalControlModels_s/glider_s.jl @@ -104,14 +104,14 @@ function OptimalControlProblems.glider_s( end # initial guess - tfinit = 60.0 + tfinit = 100.0 xinit = t -> [ - x_t0 + vx_t0 * t, + x_t0 + (t / tfinit) * 1248.0, y_t0 + (t / tfinit) * (y_tf - y_t0), vx_t0 + (t / tfinit) * (vx_tf - vx_t0), vy_t0 + (t / tfinit) * (vy_tf - vy_t0) ] - uinit = (cL_min + cL_max) / 2 + uinit = 1.0 init = (state=xinit, control=uinit, variable=tfinit) # discretise the optimal control problem diff --git a/ext/OptimalControlModels_s/space_shuttle_s.jl b/ext/OptimalControlModels_s/space_shuttle_s.jl index 14951a91..77b4df0e 100644 --- a/ext/OptimalControlModels_s/space_shuttle_s.jl +++ b/ext/OptimalControlModels_s/space_shuttle_s.jl @@ -56,8 +56,8 @@ function OptimalControlProblems.space_shuttle_s( # Δt_min = params[:Δt_min] Δt_max = params[:Δt_max] - tf_l = grid_size*Δt_min - tf_u = grid_size*Δt_max + tf_l = 1500.0 # + tf_u = 2500.0 # ## Initial conditions h_t0 = params[:h_t0] @@ -164,7 +164,7 @@ function OptimalControlProblems.space_shuttle_s( # initial guess: linear interpolation for h, v, gamma (NB. t0 = 0), constant for the rest # variable time step seems to be initialized at 1 in jump # note that ipopt will project the initial guess inside the bounds anyway. - tf_init = 0.5 + tf_init = 2000 x_init = t -> [ h_t0 + (t - t0) / (tf_init - t0) * (h_tf - h_t0), From cdbebe27a934ed1e7d50c3fd0b49d67fd7cb0a62 Mon Sep 17 00:00:00 2001 From: Amiel Date: Thu, 29 Jan 2026 15:20:30 +0100 Subject: [PATCH 05/24] remove exclude problems --- src/OptimalControlProblems.jl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/OptimalControlProblems.jl b/src/OptimalControlProblems.jl index 9729407d..f554f1db 100644 --- a/src/OptimalControlProblems.jl +++ b/src/OptimalControlProblems.jl @@ -68,10 +68,10 @@ function make_list_of_problems() :dielectrophoretic_particle, :moonlander, :ducted_fan, - :insurance, - :robot, - :space_shuttle, - :steering, + #:insurance, + #:robot, + #:space_shuttle, + #:steering, ] list_of_problems = setdiff(list_of_problems, problems_to_exclude) From a1119740024c72ddeea854bf44943c92f594808b Mon Sep 17 00:00:00 2001 From: Amiel Date: Thu, 29 Jan 2026 16:16:56 +0100 Subject: [PATCH 06/24] try fix robot crash --- ext/JuMPModels/robot.jl | 51 +++++++++++++++++++++------ ext/OptimalControlModels/robot.jl | 31 +++++++++------- ext/OptimalControlModels_s/robot_s.jl | 35 ++++++++++++------ 3 files changed, 84 insertions(+), 33 deletions(-) diff --git a/ext/JuMPModels/robot.jl b/ext/JuMPModels/robot.jl index a77ffe80..2acfb9ca 100644 --- a/ext/JuMPModels/robot.jl +++ b/ext/JuMPModels/robot.jl @@ -92,22 +92,53 @@ function OptimalControlProblems.robot( @variables( model, begin - ρ_l ≤ ρ[k = 0:N] ≤ ρ_u, (start = ρ_t0) - θ_l ≤ θ[k = 0:N] ≤ θ_u, (start = 2π/3 * (k / N)^2) - ϕ_l ≤ ϕ[k = 0:N] ≤ ϕ_u, (start = ϕ_t0) + ρ_l ≤ ρ[k = 0:N] ≤ ρ_u + θ_l ≤ θ[k = 0:N] ≤ θ_u + ϕ_l ≤ ϕ[k = 0:N] ≤ ϕ_u - dρ[k = 0:N], (start = 0) - dθ[k = 0:N], (start = 4π/3 * (k / N)) - dϕ[k = 0:N], (start = 0) + dρ[k = 0:N] + dθ[k = 0:N] + dϕ[k = 0:N] - uρ_l ≤ uρ[0:N] ≤ uρ_u, (start = 0) - uθ_l ≤ uθ[0:N] ≤ uθ_u, (start = 0) - uϕ_l ≤ uϕ[0:N] ≤ uϕ_u, (start = 0) + uρ_l ≤ uρ[0:N] ≤ uρ_u + uθ_l ≤ uθ[0:N] ≤ uθ_u + uϕ_l ≤ uϕ[0:N] ≤ uϕ_u - tf ≥ tf_l, (start = 9.1) + tf ≥ tf_l end ) + #INITIAL GUESS + set_start_value(tf, 9.1) + for k in 0:grid_size + # Coefficient d'interpolation entre 0 et 1 + alpha = k / grid_size + + # Interpolation linéaire entre t0 et tf + ρ_val = ρ_t0 + alpha * (ρ_tf - ρ_t0) + θ_val = θ_t0 + alpha * (θ_tf - θ_t0) + ϕ_val = ϕ_t0 + alpha * (ϕ_tf - ϕ_t0) + + # SECURITÉ ANTI-CRASH (Division par zéro) + if abs(ϕ_val) < 1e-6 + ϕ_val = 1e-6 + end + + # Application des valeurs aux variables JuMP + set_start_value(ρ[k], ρ_val) + set_start_value(θ[k], θ_val) + set_start_value(ϕ[k], ϕ_val) + + # Vitesses et contrôles à 0 par défaut + set_start_value(dρ[k], 0.0) + set_start_value(dθ[k], 0.0) + set_start_value(dϕ[k], 0.0) + + set_start_value(uρ[k], 0.0) + set_start_value(uθ[k], 0.0) + set_start_value(uϕ[k], 0.0) + end + # Boundary condition @constraints( model, diff --git a/ext/OptimalControlModels/robot.jl b/ext/OptimalControlModels/robot.jl index 72859325..068bae89 100644 --- a/ext/OptimalControlModels/robot.jl +++ b/ext/OptimalControlModels/robot.jl @@ -117,18 +117,25 @@ function OptimalControlProblems.robot( end # initial guess - tf = 9.1 - xinit = - t -> [ - ρ_t0, - 0, - 2π/3 * ((t - t0) / (tf - t0))^2, - 4π/3 * ((t - t0) / (tf - t0)), - ϕ_t0, - 0, - ] - uinit = [0, 0, 0] - init = (state=xinit, control=uinit, variable=tf) + tf_guess = 9.1 # On renomme pour éviter la confusion avec la variable symbolique + + xinit = t -> begin + alpha = clamp((t - t0) / (tf_guess - t0), 0.0, 1.0) + + + ρ_val = ρ_t0 + alpha * (ρ_tf - ρ_t0) + θ_val = θ_t0 + alpha * (θ_tf - θ_t0) + ϕ_val = ϕ_t0 + alpha * (ϕ_tf - ϕ_t0) + + if abs(ϕ_val) < 1e-6 + ϕ_val = 1e-6 + end + + return [ρ_val,0.0,θ_val,0.0,ϕ_val,0.0] + end + + uinit = [0.0, 0.0, 0.0] + init = (state=xinit, control=uinit, variable=tf_guess) # discretise the optimal control problem docp = direct_transcription( diff --git a/ext/OptimalControlModels_s/robot_s.jl b/ext/OptimalControlModels_s/robot_s.jl index c7b2fbda..6db8b146 100644 --- a/ext/OptimalControlModels_s/robot_s.jl +++ b/ext/OptimalControlModels_s/robot_s.jl @@ -122,18 +122,31 @@ function OptimalControlProblems.robot_s( end # initial guess - tf = 9.1 - xinit = - t -> [ - ρ_t0, - 0, - 2π/3 * ((t - t0) / (tf - t0))^2, - 4π/3 * ((t - t0) / (tf - t0)), - ϕ_t0, - 0, + tf_guess = 9.1 + + xinit = t -> begin + alpha = clamp((t - t0) / (tf_guess - t0), 0.0, 1.0) + + ρ_val = ρ_t0 + alpha * (ρ_tf - ρ_t0) + θ_val = θ_t0 + alpha * (θ_tf - θ_t0) + ϕ_val = ϕ_t0 + alpha * (ϕ_tf - ϕ_t0) + + if abs(ϕ_val) < 1e-6 + ϕ_val = 1e-6 + end + + return [ + ρ_val, + 0.0, + θ_val, + 0.0, + ϕ_val, + 0.0, ] - uinit = [0, 0, 0] - init = (state=xinit, control=uinit, variable=tf) + end + + uinit = [0.0, 0.0, 0.0] + init = (state=xinit, control=uinit, variable=tf_guess) # discretise the optimal control problem docp = direct_transcription( From 15d480a51913eafe8b540ca1acdf29a42f89d654 Mon Sep 17 00:00:00 2001 From: Amiel Date: Thu, 29 Jan 2026 16:50:02 +0100 Subject: [PATCH 07/24] try to fix robot 2 --- ext/JuMPModels/robot.jl | 3 +-- ext/OptimalControlModels/robot.jl | 21 +++++++++++++-------- ext/OptimalControlModels_s/robot_s.jl | 12 +++++------- 3 files changed, 19 insertions(+), 17 deletions(-) diff --git a/ext/JuMPModels/robot.jl b/ext/JuMPModels/robot.jl index 2acfb9ca..bc109fba 100644 --- a/ext/JuMPModels/robot.jl +++ b/ext/JuMPModels/robot.jl @@ -168,8 +168,7 @@ function OptimalControlProblems.robot( # Δt, (tf - t0) / N - # - I_θ[i = 0:N], ((L - ρ[i])^3 + ρ[i]^3) * (sin(ϕ[i]))^2 + I_θ[i = 0:N], ((L - ρ[i])^3 + ρ[i]^3) * ((sin(ϕ[i]))^2 + 1e-9) I_ϕ[i = 0:N], (L - ρ[i])^3 + ρ[i]^3 # diff --git a/ext/OptimalControlModels/robot.jl b/ext/OptimalControlModels/robot.jl index 068bae89..454ab55b 100644 --- a/ext/OptimalControlModels/robot.jl +++ b/ext/OptimalControlModels/robot.jl @@ -105,24 +105,22 @@ function OptimalControlProblems.robot( dθ(tf) == dθ_tf, (dθ_tf) dϕ(tf) == dϕ_tf, (dϕ_tf) - # aliases - I_θ = ((L - ρ(t))^3 + ρ(t)^3) * sin(ϕ(t))^2 + + I_θ = ((L - ρ(t))^3 + ρ(t)^3) * (sin(ϕ(t))^2 + 1e-9) I_ϕ = (L - ρ(t))^3 + ρ(t)^3 # dynamics - ẋ(t) == [dρ(t), uρ(t) / L, dθ(t), 3 * uθ(t) / I_θ, dϕ(t), 3 * uϕ(t) / I_ϕ] + ẋ(t) == [dρ(t), uρ(t) / L, dθ(t), 3 * uθ(t) / I_θ, dϕ(t), 3 * uϕ(t) / I_ϕ] # objective tf → min end # initial guess - tf_guess = 9.1 # On renomme pour éviter la confusion avec la variable symbolique - + tf_guess = 9.1 xinit = t -> begin alpha = clamp((t - t0) / (tf_guess - t0), 0.0, 1.0) - ρ_val = ρ_t0 + alpha * (ρ_tf - ρ_t0) θ_val = θ_t0 + alpha * (θ_tf - θ_t0) ϕ_val = ϕ_t0 + alpha * (ϕ_tf - ϕ_t0) @@ -131,9 +129,16 @@ function OptimalControlProblems.robot( ϕ_val = 1e-6 end - return [ρ_val,0.0,θ_val,0.0,ϕ_val,0.0] + return [ + ρ_val, + 0.0, + θ_val, + 0.0, + ϕ_val, + 0.0, + ] end - + uinit = [0.0, 0.0, 0.0] init = (state=xinit, control=uinit, variable=tf_guess) diff --git a/ext/OptimalControlModels_s/robot_s.jl b/ext/OptimalControlModels_s/robot_s.jl index 6db8b146..b9f245fe 100644 --- a/ext/OptimalControlModels_s/robot_s.jl +++ b/ext/OptimalControlModels_s/robot_s.jl @@ -106,7 +106,7 @@ function OptimalControlProblems.robot_s( dϕ(tf) == dϕ_tf, (dϕ_tf) # aliases - I_θ = ((L - ρ(t))^3 + ρ(t)^3) * sin(ϕ(t))^2 + I_θ = ((L - ρ(t))^3 + ρ(t)^3) * (sin(ϕ(t))^2 + 1e-9) I_ϕ = (L - ρ(t))^3 + ρ(t)^3 # dynamics @@ -123,10 +123,9 @@ function OptimalControlProblems.robot_s( # initial guess tf_guess = 9.1 - xinit = t -> begin alpha = clamp((t - t0) / (tf_guess - t0), 0.0, 1.0) - + ρ_val = ρ_t0 + alpha * (ρ_tf - ρ_t0) θ_val = θ_t0 + alpha * (θ_tf - θ_t0) ϕ_val = ϕ_t0 + alpha * (ϕ_tf - ϕ_t0) @@ -137,14 +136,13 @@ function OptimalControlProblems.robot_s( return [ ρ_val, - 0.0, + 0.0, θ_val, - 0.0, + 0.0, ϕ_val, - 0.0, + 0.0, ] end - uinit = [0.0, 0.0, 0.0] init = (state=xinit, control=uinit, variable=tf_guess) From 432fc71eda6504e6995338f041e1bb3a93bbe31c Mon Sep 17 00:00:00 2001 From: Amiel Date: Thu, 29 Jan 2026 18:26:54 +0100 Subject: [PATCH 08/24] remove robot --- src/OptimalControlProblems.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/OptimalControlProblems.jl b/src/OptimalControlProblems.jl index f554f1db..092b4a00 100644 --- a/src/OptimalControlProblems.jl +++ b/src/OptimalControlProblems.jl @@ -69,7 +69,7 @@ function make_list_of_problems() :moonlander, :ducted_fan, #:insurance, - #:robot, + :robot, #:space_shuttle, #:steering, ] From a1bc627f5046d87c30115e3fee5a4c3eea91ca3d Mon Sep 17 00:00:00 2001 From: Amiel Date: Thu, 29 Jan 2026 18:50:41 +0100 Subject: [PATCH 09/24] remove space --- src/OptimalControlProblems.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/OptimalControlProblems.jl b/src/OptimalControlProblems.jl index 092b4a00..799926d6 100644 --- a/src/OptimalControlProblems.jl +++ b/src/OptimalControlProblems.jl @@ -70,7 +70,7 @@ function make_list_of_problems() :ducted_fan, #:insurance, :robot, - #:space_shuttle, + :space_shuttle, #:steering, ] list_of_problems = setdiff(list_of_problems, problems_to_exclude) From 039663dffe26c32ffd8ad6e7e0895c5880dc6d74 Mon Sep 17 00:00:00 2001 From: Amiel Date: Sun, 1 Feb 2026 00:42:23 +0100 Subject: [PATCH 10/24] try to add bioreactor --- ext/JuMPModels/bioreactor.jl | 14 +-- ext/OptimalControlModels/bioreactor.jl | 4 +- ext/OptimalControlModels_s/bioreactor_s.jl | 104 +++++++++++++++++++++ src/OptimalControlProblems.jl | 2 - 4 files changed, 113 insertions(+), 11 deletions(-) create mode 100644 ext/OptimalControlModels_s/bioreactor_s.jl diff --git a/ext/JuMPModels/bioreactor.jl b/ext/JuMPModels/bioreactor.jl index aa2d27e7..4950a024 100644 --- a/ext/JuMPModels/bioreactor.jl +++ b/ext/JuMPModels/bioreactor.jl @@ -79,10 +79,10 @@ function OptimalControlProblems.bioreactor( @variables( model, begin - y[0:N] ≥ y_l, (start = 50) - s[0:N] ≥ s_l, (start = 50) - b[0:N] ≥ b_l, (start = 50) - u_l ≤ u[0:N] ≤ u_u, (start = 0.5) + y[0:N] ≥ 0, (start = 0.15) + s[0:N] ≥ 0, (start = 2.75) + b[0:N] ≥ 0.001, (start = 1.75) + 0 ≤ u[0:N] ≤ 1, (start = 0.5) end ) @@ -90,9 +90,9 @@ function OptimalControlProblems.bioreactor( @constraints( model, begin - y_t0_l ≤ y[0] ≤ y_t0_u - s_t0_l ≤ s[0] ≤ s_t0_u - b_t0_l ≤ b[0] ≤ b_t0_u + y[0] == 0.05 + s[0] == 0.5 + b[0] == 0.5 end ) diff --git a/ext/OptimalControlModels/bioreactor.jl b/ext/OptimalControlModels/bioreactor.jl index 3f32d976..4f3f3c6c 100644 --- a/ext/OptimalControlModels/bioreactor.jl +++ b/ext/OptimalControlModels/bioreactor.jl @@ -65,7 +65,7 @@ function OptimalControlProblems.bioreactor( x = (y, s, b) ∈ R³, state u ∈ R, control - x(t) ≥ [y_l, s_l, b_l] + x(t) ≥ [0, 0, 1e-3] u_l ≤ u(t) ≤ u_u [y_t0_l, s_t0_l, b_t0_l] ≤ x(t0) ≤ [y_t0_u, s_t0_u, b_t0_u] @@ -100,7 +100,7 @@ function OptimalControlProblems.bioreactor( end # initial guess - init = (state=[50, 50, 50], control=0.5) + init = (state=[0.15, 2.75, 1.75], control=0.5) # discretise the optimal control problem docp = direct_transcription( diff --git a/ext/OptimalControlModels_s/bioreactor_s.jl b/ext/OptimalControlModels_s/bioreactor_s.jl new file mode 100644 index 00000000..ea5dbf50 --- /dev/null +++ b/ext/OptimalControlModels_s/bioreactor_s.jl @@ -0,0 +1,104 @@ +""" +$(TYPEDSIGNATURES) + +Constructs an **OptimalControl problem** representing the **Bioreactor problem** with **fixed initial conditions**. +The function sets up the state variables (algae , substrate , biomass ), the control variable (flow rate ), and the specific dynamics governing the photobioreactor-digester coupling. + +Unlike the general case, this version (`_s`) fixes the initial state to a specific point x(0) = [0.05, 0.5, 0.5] and enforces a safety constraint b(t) ge 10^{-3} to prevent biomass washout. + +It performs direct transcription to generate a discrete optimal control problem (DOCP). + +# Arguments + +- `::OptimalControlBackend`: Placeholder type specifying the OptimalControl backend or solver interface. +- `grid_size::Int=grid_size_data(:bioreactor)`: (Keyword) Number of discretisation points for the direct transcription grid. + +# Returns + +- `docp`: The direct optimal control problem object representing the discretised Bioreactor problem. + +# Example + +```julia-repl +julia> using OptimalControlProblems + +julia> docp = OptimalControlProblems.bioreactor(OptimalControlBackend(); N=100); +``` +""" + +function OptimalControlProblems.bioreactor_s( + ::OptimalControlBackend, + description::Symbol...; + grid_size::Int=grid_size_data(:bioreactor), + parameters::Union{Nothing,NamedTuple}=nothing, + kwargs..., +) + # --- 1. Parameters --- + params = parameters_data(:bioreactor, parameters) + # Retrieve physical constants + t0 = params[:t0] + tf = params[:tf] + β, c, γ = params[:β], params[:c], params[:γ] + halfperiod = params[:halfperiod] + Ks, μ2m, μbar, r = params[:Ks], params[:μ2m], params[:μbar], params[:r] + + # --- 2. The Model --- + ocp = @def begin + t ∈ [t0, tf], time + x = (y, s, b) ∈ R³, state + u ∈ R, control + + # Simple bound constraints (Step B: discrete method) + # Ensure non-negativity and biomass survival + y(t) ≥ 0 + s(t) ≥ 0 + b(t) ≥ 0.001 # The safety constraint + 0 ≤ u(t) ≤ 1 + + # FIXED INITIAL CONDITIONS (The "_s" suffix) + # Fixing start exactly at lower bounds of the original problem + x(t0) == [0.05, 0.5, 0.5] + + # Dynamics (Light + Growth) + μ = light(t, halfperiod) * μbar + μ2 = growth(s(t), μ2m, Ks) + + ẋ(t) == [ + μ * y(t) / (1 + y(t)) - (r + u(t)) * y(t), + -μ2 * b(t) + u(t) * β * (γ * y(t) - s(t)), + (μ2 - u(t) * β) * b(t) + ] + + # Objective: Maximize methane (Minimize the opposite) + -∫(μ2 * b(t) / (β + c)) → min + end + + # --- 3. Auxiliary functions --- + function growth(s, μ2m, Ks) + return μ2m * s / (s + Ks) + end + + function light(time, halfperiod) + days = time / (halfperiod * 2) + tau = (days - floor(days)) * 2π + return max(0, sin(tau))^2 + end + + # --- 4. Initialization (CRITICAL) --- + # Start with constant state equal to initial point + # and average control (0.5) to help the solver + init = (state=[0.05, 0.5, 0.5], control=0.5) + + # --- 5. Transcription --- + docp = direct_transcription( + ocp, + description...; + lagrange_to_mayer=false, + init=init, + grid_size=grid_size, + disc_method=:trapeze, + kwargs..., + ) + + return docp +end \ No newline at end of file diff --git a/src/OptimalControlProblems.jl b/src/OptimalControlProblems.jl index 799926d6..0f95e379 100644 --- a/src/OptimalControlProblems.jl +++ b/src/OptimalControlProblems.jl @@ -68,10 +68,8 @@ function make_list_of_problems() :dielectrophoretic_particle, :moonlander, :ducted_fan, - #:insurance, :robot, :space_shuttle, - #:steering, ] list_of_problems = setdiff(list_of_problems, problems_to_exclude) From bef937b3b6d4682d7a60fd6a92e23e94c47e3463 Mon Sep 17 00:00:00 2001 From: Amiel Date: Sun, 1 Feb 2026 00:43:34 +0100 Subject: [PATCH 11/24] remove bioreactor to exclude --- src/OptimalControlProblems.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/OptimalControlProblems.jl b/src/OptimalControlProblems.jl index 0f95e379..d13dd18b 100644 --- a/src/OptimalControlProblems.jl +++ b/src/OptimalControlProblems.jl @@ -63,7 +63,7 @@ function make_list_of_problems() # exclude the following problems problems_to_exclude = [ - :bioreactor, + #:bioreactor, :cart_pendulum, :dielectrophoretic_particle, :moonlander, From 8179d90e102bb0e01173e4354036f462302a6fc5 Mon Sep 17 00:00:00 2001 From: Amiel Date: Sun, 1 Feb 2026 00:57:01 +0100 Subject: [PATCH 12/24] fix error bioreactor --- ext/OptimalControlModels/bioreactor.jl | 8 +++----- ext/OptimalControlModels_s/bioreactor_s.jl | 8 +++----- 2 files changed, 6 insertions(+), 10 deletions(-) diff --git a/ext/OptimalControlModels/bioreactor.jl b/ext/OptimalControlModels/bioreactor.jl index 4f3f3c6c..cd42cfd0 100644 --- a/ext/OptimalControlModels/bioreactor.jl +++ b/ext/OptimalControlModels/bioreactor.jl @@ -72,11 +72,9 @@ function OptimalControlProblems.bioreactor( μ = light(t, halfperiod) * μbar μ2 = growth(s(t), μ2m, Ks) - ẋ(t) == [ - μ * y(t) / (1 + y(t)) - (r + u(t)) * y(t), - -μ2 * b(t) + u(t) * β * (γ * y(t) - s(t)), - (μ2 - u(t) * β) * b(t), - ] + ẋ[1](t) == μ * y(t) / (1 + y(t)) - (r + u(t)) * y(t) + ẋ[2](t) == -μ2 * b(t) + u(t) * β * (γ * y(t) - s(t)) + ẋ[3](t) == (μ2 - u(t) * β) * b(t) -∫(μ2 * b(t) / (β + c)) → min end diff --git a/ext/OptimalControlModels_s/bioreactor_s.jl b/ext/OptimalControlModels_s/bioreactor_s.jl index ea5dbf50..d23866d9 100644 --- a/ext/OptimalControlModels_s/bioreactor_s.jl +++ b/ext/OptimalControlModels_s/bioreactor_s.jl @@ -63,11 +63,9 @@ function OptimalControlProblems.bioreactor_s( μ = light(t, halfperiod) * μbar μ2 = growth(s(t), μ2m, Ks) - ẋ(t) == [ - μ * y(t) / (1 + y(t)) - (r + u(t)) * y(t), - -μ2 * b(t) + u(t) * β * (γ * y(t) - s(t)), - (μ2 - u(t) * β) * b(t) - ] + ẋ[1](t) == μ * y(t) / (1 + y(t)) - (r + u(t)) * y(t) + ẋ[2](t) == -μ2 * b(t) + u(t) * β * (γ * y(t) - s(t)) + ẋ[3](t) == (μ2 - u(t) * β) * b(t) # Objective: Maximize methane (Minimize the opposite) -∫(μ2 * b(t) / (β + c)) → min From 7a9af874e35416d6c9b52d0dd283bdbeaf308de5 Mon Sep 17 00:00:00 2001 From: Amiel Date: Sun, 1 Feb 2026 01:04:38 +0100 Subject: [PATCH 13/24] fix 2 biorecator --- ext/OptimalControlModels/bioreactor.jl | 37 ++++++++++++---------- ext/OptimalControlModels_s/bioreactor_s.jl | 22 ++++++------- 2 files changed, 31 insertions(+), 28 deletions(-) diff --git a/ext/OptimalControlModels/bioreactor.jl b/ext/OptimalControlModels/bioreactor.jl index cd42cfd0..c7a3f0c7 100644 --- a/ext/OptimalControlModels/bioreactor.jl +++ b/ext/OptimalControlModels/bioreactor.jl @@ -59,6 +59,26 @@ function OptimalControlProblems.bioreactor( b_t0_l = params[:b_t0_l] b_t0_u = params[:b_t0_u] + + # METHANE PROBLEM + # μ2 according to growth model + # μ according to light model + # time scale is [0,10] for 24h (day then night) + + # growth model MONOD + function growth(s, μ2m, Ks) + return μ2m * s / (s + Ks) + end + + # light model: max^2 (0,sin) * μbar + # DAY/NIGHT CYCLE: [0,2 halfperiod] rescaled to [0,2pi] + function light(time, halfperiod) + days = time / (halfperiod * 2) + tau = (days - floor(days)) * 2π + return max(0, sin(tau))^2 + end + + # Model ocp = @def begin t ∈ [t0, tf], time @@ -79,23 +99,6 @@ function OptimalControlProblems.bioreactor( -∫(μ2 * b(t) / (β + c)) → min end - # METHANE PROBLEM - # μ2 according to growth model - # μ according to light model - # time scale is [0,10] for 24h (day then night) - - # growth model MONOD - function growth(s, μ2m, Ks) - return μ2m * s / (s + Ks) - end - - # light model: max^2 (0,sin) * μbar - # DAY/NIGHT CYCLE: [0,2 halfperiod] rescaled to [0,2pi] - function light(time, halfperiod) - days = time / (halfperiod * 2) - tau = (days - floor(days)) * 2π - return max(0, sin(tau))^2 - end # initial guess init = (state=[0.15, 2.75, 1.75], control=0.5) diff --git a/ext/OptimalControlModels_s/bioreactor_s.jl b/ext/OptimalControlModels_s/bioreactor_s.jl index d23866d9..ee127302 100644 --- a/ext/OptimalControlModels_s/bioreactor_s.jl +++ b/ext/OptimalControlModels_s/bioreactor_s.jl @@ -42,6 +42,17 @@ function OptimalControlProblems.bioreactor_s( halfperiod = params[:halfperiod] Ks, μ2m, μbar, r = params[:Ks], params[:μ2m], params[:μbar], params[:r] + # --- 3. Auxiliary functions --- + function growth(s, μ2m, Ks) + return μ2m * s / (s + Ks) + end + + function light(time, halfperiod) + days = time / (halfperiod * 2) + tau = (days - floor(days)) * 2π + return max(0, sin(tau))^2 + end + # --- 2. The Model --- ocp = @def begin t ∈ [t0, tf], time @@ -71,17 +82,6 @@ function OptimalControlProblems.bioreactor_s( -∫(μ2 * b(t) / (β + c)) → min end - # --- 3. Auxiliary functions --- - function growth(s, μ2m, Ks) - return μ2m * s / (s + Ks) - end - - function light(time, halfperiod) - days = time / (halfperiod * 2) - tau = (days - floor(days)) * 2π - return max(0, sin(tau))^2 - end - # --- 4. Initialization (CRITICAL) --- # Start with constant state equal to initial point # and average control (0.5) to help the solver From 49d15e9ce323c54b433fcf482a6a81f6c7f7ec4c Mon Sep 17 00:00:00 2001 From: Amiel Date: Sun, 1 Feb 2026 01:15:41 +0100 Subject: [PATCH 14/24] fix 3 bioreactor --- ext/OptimalControlModels/bioreactor.jl | 68 +++++++--------------- ext/OptimalControlModels_s/bioreactor_s.jl | 42 +++++-------- 2 files changed, 37 insertions(+), 73 deletions(-) diff --git a/ext/OptimalControlModels/bioreactor.jl b/ext/OptimalControlModels/bioreactor.jl index c7a3f0c7..9697107e 100644 --- a/ext/OptimalControlModels/bioreactor.jl +++ b/ext/OptimalControlModels/bioreactor.jl @@ -34,76 +34,52 @@ function OptimalControlProblems.bioreactor( parameters::Union{Nothing,NamedTuple}=nothing, kwargs..., ) - - # parameters + # --- 1. Paramètres --- params = parameters_data(:bioreactor, parameters) - t0 = params[:t0] - tf = params[:tf] - β = params[:β] - c = params[:c] - γ = params[:γ] + t0, tf = params[:t0], params[:tf] + β, c, γ = params[:β], params[:c], params[:γ] halfperiod = params[:halfperiod] - Ks = params[:Ks] - μ2m = params[:μ2m] - μbar = params[:μbar] - r = params[:r] - y_l = params[:y_l] - s_l = params[:s_l] - b_l = params[:b_l] - u_l = params[:u_l] - u_u = params[:u_u] - y_t0_l = params[:y_t0_l] - y_t0_u = params[:y_t0_u] - s_t0_l = params[:s_t0_l] - s_t0_u = params[:s_t0_u] - b_t0_l = params[:b_t0_l] - b_t0_u = params[:b_t0_u] - - - # METHANE PROBLEM - # μ2 according to growth model - # μ according to light model - # time scale is [0,10] for 24h (day then night) - - # growth model MONOD + Ks, μ2m, μbar, r = params[:Ks], params[:μ2m], params[:μbar], params[:r] + y_l, s_l, b_l = params[:y_l], params[:s_l], params[:b_l] + u_l, u_u = params[:u_l], params[:u_u] + y_t0_l, y_t0_u = params[:y_t0_l], params[:y_t0_u] + s_t0_l, s_t0_u = params[:s_t0_l], params[:s_t0_u] + b_t0_l, b_t0_u = params[:b_t0_l], params[:b_t0_u] + + # --- 2. Fonctions Utilitaires (AVANT @def) --- function growth(s, μ2m, Ks) return μ2m * s / (s + Ks) end - # light model: max^2 (0,sin) * μbar - # DAY/NIGHT CYCLE: [0,2 halfperiod] rescaled to [0,2pi] function light(time, halfperiod) days = time / (halfperiod * 2) tau = (days - floor(days)) * 2π return max(0, sin(tau))^2 end - - # Model + # --- 3. Modèle --- ocp = @def begin t ∈ [t0, tf], time x = (y, s, b) ∈ R³, state u ∈ R, control + # Contraintes bornes x(t) ≥ [0, 0, 1e-3] u_l ≤ u(t) ≤ u_u [y_t0_l, s_t0_l, b_t0_l] ≤ x(t0) ≤ [y_t0_u, s_t0_u, b_t0_u] - μ = light(t, halfperiod) * μbar - μ2 = growth(s(t), μ2m, Ks) - - ẋ[1](t) == μ * y(t) / (1 + y(t)) - (r + u(t)) * y(t) - ẋ[2](t) == -μ2 * b(t) + u(t) * β * (γ * y(t) - s(t)) - ẋ[3](t) == (μ2 - u(t) * β) * b(t) + # Dynamique (Calculs "inline" sans variables intermédiaires) + ẋ[1](t) == (light(t, halfperiod) * μbar) * y(t) / (1 + y(t)) - (r + u(t)) * y(t) + ẋ[2](t) == -growth(s(t), μ2m, Ks) * b(t) + u(t) * β * (γ * y(t) - s(t)) + ẋ[3](t) == (growth(s(t), μ2m, Ks) - u(t) * β) * b(t) - -∫(μ2 * b(t) / (β + c)) → min + # Objectif + -∫(growth(s(t), μ2m, Ks) * b(t) / (β + c)) → min end - - # initial guess + # --- 4. Transcription --- init = (state=[0.15, 2.75, 1.75], control=0.5) - - # discretise the optimal control problem + docp = direct_transcription( ocp, description...; @@ -115,4 +91,4 @@ function OptimalControlProblems.bioreactor( ) return docp -end +end \ No newline at end of file diff --git a/ext/OptimalControlModels_s/bioreactor_s.jl b/ext/OptimalControlModels_s/bioreactor_s.jl index ee127302..1e7099f9 100644 --- a/ext/OptimalControlModels_s/bioreactor_s.jl +++ b/ext/OptimalControlModels_s/bioreactor_s.jl @@ -33,16 +33,14 @@ function OptimalControlProblems.bioreactor_s( parameters::Union{Nothing,NamedTuple}=nothing, kwargs..., ) - # --- 1. Parameters --- + # --- 1. Paramètres --- params = parameters_data(:bioreactor, parameters) - # Retrieve physical constants - t0 = params[:t0] - tf = params[:tf] + t0, tf = params[:t0], params[:tf] β, c, γ = params[:β], params[:c], params[:γ] halfperiod = params[:halfperiod] Ks, μ2m, μbar, r = params[:Ks], params[:μ2m], params[:μbar], params[:r] - # --- 3. Auxiliary functions --- + # --- 2. Fonctions Utilitaires (AVANT @def) --- function growth(s, μ2m, Ks) return μ2m * s / (s + Ks) end @@ -53,41 +51,31 @@ function OptimalControlProblems.bioreactor_s( return max(0, sin(tau))^2 end - # --- 2. The Model --- + # --- 3. Modèle --- ocp = @def begin t ∈ [t0, tf], time x = (y, s, b) ∈ R³, state u ∈ R, control - # Simple bound constraints (Step B: discrete method) - # Ensure non-negativity and biomass survival - y(t) ≥ 0 - s(t) ≥ 0 - b(t) ≥ 0.001 # The safety constraint + # Contraintes bornes + x(t) ≥ [0, 0, 1e-3] 0 ≤ u(t) ≤ 1 - # FIXED INITIAL CONDITIONS (The "_s" suffix) - # Fixing start exactly at lower bounds of the original problem - x(t0) == [0.05, 0.5, 0.5] + # Conditions initiales FIXES + x(t0) == [0.05, 0.5, 0.5] - # Dynamics (Light + Growth) - μ = light(t, halfperiod) * μbar - μ2 = growth(s(t), μ2m, Ks) + # Dynamique (Calculs "inline") + ẋ[1](t) == (light(t, halfperiod) * μbar) * y(t) / (1 + y(t)) - (r + u(t)) * y(t) + ẋ[2](t) == -growth(s(t), μ2m, Ks) * b(t) + u(t) * β * (γ * y(t) - s(t)) + ẋ[3](t) == (growth(s(t), μ2m, Ks) - u(t) * β) * b(t) - ẋ[1](t) == μ * y(t) / (1 + y(t)) - (r + u(t)) * y(t) - ẋ[2](t) == -μ2 * b(t) + u(t) * β * (γ * y(t) - s(t)) - ẋ[3](t) == (μ2 - u(t) * β) * b(t) - - # Objective: Maximize methane (Minimize the opposite) - -∫(μ2 * b(t) / (β + c)) → min + # Objectif + -∫(growth(s(t), μ2m, Ks) * b(t) / (β + c)) → min end - # --- 4. Initialization (CRITICAL) --- - # Start with constant state equal to initial point - # and average control (0.5) to help the solver + # --- 4. Transcription --- init = (state=[0.05, 0.5, 0.5], control=0.5) - # --- 5. Transcription --- docp = direct_transcription( ocp, description...; From 3fab237b4eb2b493f1405031364de0c1de9f8cfc Mon Sep 17 00:00:00 2001 From: Amiel Date: Sun, 1 Feb 2026 16:06:27 +0100 Subject: [PATCH 15/24] try fix crash bioreactor --- ext/OptimalControlModels/bioreactor.jl | 29 ++++++++-------------- ext/OptimalControlModels_s/bioreactor_s.jl | 29 ++++++++-------------- 2 files changed, 21 insertions(+), 37 deletions(-) diff --git a/ext/OptimalControlModels/bioreactor.jl b/ext/OptimalControlModels/bioreactor.jl index 9697107e..9f4d8331 100644 --- a/ext/OptimalControlModels/bioreactor.jl +++ b/ext/OptimalControlModels/bioreactor.jl @@ -46,35 +46,28 @@ function OptimalControlProblems.bioreactor( s_t0_l, s_t0_u = params[:s_t0_l], params[:s_t0_u] b_t0_l, b_t0_u = params[:b_t0_l], params[:b_t0_u] - # --- 2. Fonctions Utilitaires (AVANT @def) --- - function growth(s, μ2m, Ks) - return μ2m * s / (s + Ks) - end - - function light(time, halfperiod) - days = time / (halfperiod * 2) - tau = (days - floor(days)) * 2π - return max(0, sin(tau))^2 - end - - # --- 3. Modèle --- ocp = @def begin t ∈ [t0, tf], time x = (y, s, b) ∈ R³, state u ∈ R, control - # Contraintes bornes + # Contraintes bornes (Sécurité b >= 1e-3) x(t) ≥ [0, 0, 1e-3] u_l ≤ u(t) ≤ u_u + + # --- SPÉCIFIQUE CLASSIQUE : Inégalités --- [y_t0_l, s_t0_l, b_t0_l] ≤ x(t0) ≤ [y_t0_u, s_t0_u, b_t0_u] + # ----------------------------------------- - # Dynamique (Calculs "inline" sans variables intermédiaires) - ẋ[1](t) == (light(t, halfperiod) * μbar) * y(t) / (1 + y(t)) - (r + u(t)) * y(t) - ẋ[2](t) == -growth(s(t), μ2m, Ks) * b(t) + u(t) * β * (γ * y(t) - s(t)) - ẋ[3](t) == (growth(s(t), μ2m, Ks) - u(t) * β) * b(t) + # Dynamique Inlined (Formules directes, pas de fonctions externes) + ẋ[1](t) == (max(0, sin(t * π / halfperiod))^2 * μbar) * y(t) / (1 + y(t)) - (r + u(t)) * y(t) + + ẋ[2](t) == -(μ2m * s(t) / (s(t) + Ks)) * b(t) + u(t) * β * (γ * y(t) - s(t)) + + ẋ[3](t) == ((μ2m * s(t) / (s(t) + Ks)) - u(t) * β) * b(t) # Objectif - -∫(growth(s(t), μ2m, Ks) * b(t) / (β + c)) → min + -∫((μ2m * s(t) / (s(t) + Ks)) * b(t) / (β + c)) → min end # --- 4. Transcription --- diff --git a/ext/OptimalControlModels_s/bioreactor_s.jl b/ext/OptimalControlModels_s/bioreactor_s.jl index 1e7099f9..fb2830da 100644 --- a/ext/OptimalControlModels_s/bioreactor_s.jl +++ b/ext/OptimalControlModels_s/bioreactor_s.jl @@ -40,37 +40,28 @@ function OptimalControlProblems.bioreactor_s( halfperiod = params[:halfperiod] Ks, μ2m, μbar, r = params[:Ks], params[:μ2m], params[:μbar], params[:r] - # --- 2. Fonctions Utilitaires (AVANT @def) --- - function growth(s, μ2m, Ks) - return μ2m * s / (s + Ks) - end - - function light(time, halfperiod) - days = time / (halfperiod * 2) - tau = (days - floor(days)) * 2π - return max(0, sin(tau))^2 - end - - # --- 3. Modèle --- ocp = @def begin t ∈ [t0, tf], time x = (y, s, b) ∈ R³, state u ∈ R, control - # Contraintes bornes + # Contraintes bornes (Sécurité b >= 1e-3) x(t) ≥ [0, 0, 1e-3] 0 ≤ u(t) ≤ 1 - # Conditions initiales FIXES + # --- SPÉCIFIQUE _S : Égalité stricte --- x(t0) == [0.05, 0.5, 0.5] + # --------------------------------------- - # Dynamique (Calculs "inline") - ẋ[1](t) == (light(t, halfperiod) * μbar) * y(t) / (1 + y(t)) - (r + u(t)) * y(t) - ẋ[2](t) == -growth(s(t), μ2m, Ks) * b(t) + u(t) * β * (γ * y(t) - s(t)) - ẋ[3](t) == (growth(s(t), μ2m, Ks) - u(t) * β) * b(t) + # Dynamique Inlined (Exactement la même qu'au-dessus) + ẋ[1](t) == (max(0, sin(t * π / halfperiod))^2 * μbar) * y(t) / (1 + y(t)) - (r + u(t)) * y(t) + + ẋ[2](t) == -(μ2m * s(t) / (s(t) + Ks)) * b(t) + u(t) * β * (γ * y(t) - s(t)) + + ẋ[3](t) == ((μ2m * s(t) / (s(t) + Ks)) - u(t) * β) * b(t) # Objectif - -∫(growth(s(t), μ2m, Ks) * b(t) / (β + c)) → min + -∫((μ2m * s(t) / (s(t) + Ks)) * b(t) / (β + c)) → min end # --- 4. Transcription --- From 2cab8c3c78d6e49fa29b24395258e459182e33ef Mon Sep 17 00:00:00 2001 From: Amiel Date: Sun, 1 Feb 2026 16:29:55 +0100 Subject: [PATCH 16/24] global function bioreactor --- ext/OptimalControlModels/bioreactor.jl | 43 +++++++++++++++------- ext/OptimalControlModels_s/bioreactor_s.jl | 39 +++++++++++++------- 2 files changed, 55 insertions(+), 27 deletions(-) diff --git a/ext/OptimalControlModels/bioreactor.jl b/ext/OptimalControlModels/bioreactor.jl index 9f4d8331..a115a7b8 100644 --- a/ext/OptimalControlModels/bioreactor.jl +++ b/ext/OptimalControlModels/bioreactor.jl @@ -27,6 +27,22 @@ julia> docp = OptimalControlProblems.bioreactor(OptimalControlBackend(); N=100); - BOCOP repository: https://github.com/control-toolbox/bocop/tree/main/bocop """ + +# --- HELPER FUNCTIONS (Must be defined outside the main function) --- + +# Growth model (Monod) +function _bio_growth(s, μ2m, Ks) + return μ2m * s / (s + Ks) +end + +# Light model +function _bio_light(t, halfperiod, μbar) + # Explicit periodicity + w = π / halfperiod + return max(0, sin(w * t))^2 * μbar +end + + function OptimalControlProblems.bioreactor( ::OptimalControlBackend, description::Symbol...; @@ -34,7 +50,7 @@ function OptimalControlProblems.bioreactor( parameters::Union{Nothing,NamedTuple}=nothing, kwargs..., ) - # --- 1. Paramètres --- + # --- 1. Parameters --- params = parameters_data(:bioreactor, parameters) t0, tf = params[:t0], params[:tf] β, c, γ = params[:β], params[:c], params[:γ] @@ -46,33 +62,32 @@ function OptimalControlProblems.bioreactor( s_t0_l, s_t0_u = params[:s_t0_l], params[:s_t0_u] b_t0_l, b_t0_u = params[:b_t0_l], params[:b_t0_u] + # --- 2. Model --- ocp = @def begin t ∈ [t0, tf], time x = (y, s, b) ∈ R³, state u ∈ R, control - # Contraintes bornes (Sécurité b >= 1e-3) + # Box constraints (including safety constraint b >= 1e-3) x(t) ≥ [0, 0, 1e-3] u_l ≤ u(t) ≤ u_u - # --- SPÉCIFIQUE CLASSIQUE : Inégalités --- + # Initial conditions (Inequalities) [y_t0_l, s_t0_l, b_t0_l] ≤ x(t0) ≤ [y_t0_u, s_t0_u, b_t0_u] - # ----------------------------------------- - # Dynamique Inlined (Formules directes, pas de fonctions externes) - ẋ[1](t) == (max(0, sin(t * π / halfperiod))^2 * μbar) * y(t) / (1 + y(t)) - (r + u(t)) * y(t) - - ẋ[2](t) == -(μ2m * s(t) / (s(t) + Ks)) * b(t) + u(t) * β * (γ * y(t) - s(t)) - - ẋ[3](t) == ((μ2m * s(t) / (s(t) + Ks)) - u(t) * β) * b(t) + # Dynamics + # Using external helper functions to avoid scope errors + ẋ[1](t) == _bio_light(t, halfperiod, μbar) * y(t) / (1 + y(t)) - (r + u(t)) * y(t) + ẋ[2](t) == -_bio_growth(s(t), μ2m, Ks) * b(t) + u(t) * β * (γ * y(t) - s(t)) + ẋ[3](t) == (_bio_growth(s(t), μ2m, Ks) - u(t) * β) * b(t) - # Objectif - -∫((μ2m * s(t) / (s(t) + Ks)) * b(t) / (β + c)) → min + # Objective: Minimize negative integral (Maximize production) + -∫(_bio_growth(s(t), μ2m, Ks) * b(t) / (β + c)) → min end - # --- 4. Transcription --- + # --- 3. Transcription --- init = (state=[0.15, 2.75, 1.75], control=0.5) - + docp = direct_transcription( ocp, description...; diff --git a/ext/OptimalControlModels_s/bioreactor_s.jl b/ext/OptimalControlModels_s/bioreactor_s.jl index fb2830da..38bfc7a1 100644 --- a/ext/OptimalControlModels_s/bioreactor_s.jl +++ b/ext/OptimalControlModels_s/bioreactor_s.jl @@ -25,6 +25,20 @@ julia> using OptimalControlProblems julia> docp = OptimalControlProblems.bioreactor(OptimalControlBackend(); N=100); ``` """ +# --- HELPER FUNCTIONS (Must be defined outside the main function) --- + +# Growth model (Monod) +function _bio_growth(s, μ2m, Ks) + return μ2m * s / (s + Ks) +end + +# Light model +function _bio_light(t, halfperiod, μbar) + # Explicit periodicity + w = π / halfperiod + return max(0, sin(w * t))^2 * μbar +end + function OptimalControlProblems.bioreactor_s( ::OptimalControlBackend, @@ -33,38 +47,37 @@ function OptimalControlProblems.bioreactor_s( parameters::Union{Nothing,NamedTuple}=nothing, kwargs..., ) - # --- 1. Paramètres --- + # --- 1. Parameters --- params = parameters_data(:bioreactor, parameters) t0, tf = params[:t0], params[:tf] β, c, γ = params[:β], params[:c], params[:γ] halfperiod = params[:halfperiod] Ks, μ2m, μbar, r = params[:Ks], params[:μ2m], params[:μbar], params[:r] + # --- 2. Model --- ocp = @def begin t ∈ [t0, tf], time x = (y, s, b) ∈ R³, state u ∈ R, control - # Contraintes bornes (Sécurité b >= 1e-3) + # Box constraints (including safety constraint b >= 1e-3) x(t) ≥ [0, 0, 1e-3] 0 ≤ u(t) ≤ 1 - # --- SPÉCIFIQUE _S : Égalité stricte --- + # Initial conditions (Fixed equality) x(t0) == [0.05, 0.5, 0.5] - # --------------------------------------- - # Dynamique Inlined (Exactement la même qu'au-dessus) - ẋ[1](t) == (max(0, sin(t * π / halfperiod))^2 * μbar) * y(t) / (1 + y(t)) - (r + u(t)) * y(t) - - ẋ[2](t) == -(μ2m * s(t) / (s(t) + Ks)) * b(t) + u(t) * β * (γ * y(t) - s(t)) - - ẋ[3](t) == ((μ2m * s(t) / (s(t) + Ks)) - u(t) * β) * b(t) + # Dynamics + # Using external helper functions to avoid scope errors + ẋ[1](t) == _bio_light(t, halfperiod, μbar) * y(t) / (1 + y(t)) - (r + u(t)) * y(t) + ẋ[2](t) == -_bio_growth(s(t), μ2m, Ks) * b(t) + u(t) * β * (γ * y(t) - s(t)) + ẋ[3](t) == (_bio_growth(s(t), μ2m, Ks) - u(t) * β) * b(t) - # Objectif - -∫((μ2m * s(t) / (s(t) + Ks)) * b(t) / (β + c)) → min + # Objective: Minimize negative integral (Maximize production) + -∫(_bio_growth(s(t), μ2m, Ks) * b(t) / (β + c)) → min end - # --- 4. Transcription --- + # --- 3. Transcription --- init = (state=[0.05, 0.5, 0.5], control=0.5) docp = direct_transcription( From 47d75bb2b206d7f87150b9c065405d53600ca9f4 Mon Sep 17 00:00:00 2001 From: Amiel Date: Sun, 1 Feb 2026 16:53:21 +0100 Subject: [PATCH 17/24] test final j'en ai marre --- ext/OptimalControlModels/bioreactor.jl | 33 ++++++++-------------- ext/OptimalControlModels_s/bioreactor_s.jl | 33 +++++++--------------- 2 files changed, 21 insertions(+), 45 deletions(-) diff --git a/ext/OptimalControlModels/bioreactor.jl b/ext/OptimalControlModels/bioreactor.jl index a115a7b8..7212cf5d 100644 --- a/ext/OptimalControlModels/bioreactor.jl +++ b/ext/OptimalControlModels/bioreactor.jl @@ -28,21 +28,6 @@ julia> docp = OptimalControlProblems.bioreactor(OptimalControlBackend(); N=100); - BOCOP repository: https://github.com/control-toolbox/bocop/tree/main/bocop """ -# --- HELPER FUNCTIONS (Must be defined outside the main function) --- - -# Growth model (Monod) -function _bio_growth(s, μ2m, Ks) - return μ2m * s / (s + Ks) -end - -# Light model -function _bio_light(t, halfperiod, μbar) - # Explicit periodicity - w = π / halfperiod - return max(0, sin(w * t))^2 * μbar -end - - function OptimalControlProblems.bioreactor( ::OptimalControlBackend, description::Symbol...; @@ -75,14 +60,18 @@ function OptimalControlProblems.bioreactor( # Initial conditions (Inequalities) [y_t0_l, s_t0_l, b_t0_l] ≤ x(t0) ≤ [y_t0_u, s_t0_u, b_t0_u] - # Dynamics - # Using external helper functions to avoid scope errors - ẋ[1](t) == _bio_light(t, halfperiod, μbar) * y(t) / (1 + y(t)) - (r + u(t)) * y(t) - ẋ[2](t) == -_bio_growth(s(t), μ2m, Ks) * b(t) + u(t) * β * (γ * y(t) - s(t)) - ẋ[3](t) == (_bio_growth(s(t), μ2m, Ks) - u(t) * β) * b(t) + # Dynamics (Hard-coded formulas to avoid scope/overwrite errors) + # Light = μbar * max(0, sin(t * π / halfperiod))^2 + # Growth = μ2m * s / (s + Ks) + + ẋ[1](t) == (μbar * max(0, sin(t * π / halfperiod))^2) * y(t) / (1 + y(t)) - (r + u(t)) * y(t) + + ẋ[2](t) == -(μ2m * s(t) / (s(t) + Ks)) * b(t) + u(t) * β * (γ * y(t) - s(t)) + + ẋ[3](t) == ((μ2m * s(t) / (s(t) + Ks)) - u(t) * β) * b(t) - # Objective: Minimize negative integral (Maximize production) - -∫(_bio_growth(s(t), μ2m, Ks) * b(t) / (β + c)) → min + # Objective + -∫((μ2m * s(t) / (s(t) + Ks)) * b(t) / (β + c)) → min end # --- 3. Transcription --- diff --git a/ext/OptimalControlModels_s/bioreactor_s.jl b/ext/OptimalControlModels_s/bioreactor_s.jl index 38bfc7a1..7b7aeb50 100644 --- a/ext/OptimalControlModels_s/bioreactor_s.jl +++ b/ext/OptimalControlModels_s/bioreactor_s.jl @@ -25,20 +25,6 @@ julia> using OptimalControlProblems julia> docp = OptimalControlProblems.bioreactor(OptimalControlBackend(); N=100); ``` """ -# --- HELPER FUNCTIONS (Must be defined outside the main function) --- - -# Growth model (Monod) -function _bio_growth(s, μ2m, Ks) - return μ2m * s / (s + Ks) -end - -# Light model -function _bio_light(t, halfperiod, μbar) - # Explicit periodicity - w = π / halfperiod - return max(0, sin(w * t))^2 * μbar -end - function OptimalControlProblems.bioreactor_s( ::OptimalControlBackend, @@ -60,21 +46,22 @@ function OptimalControlProblems.bioreactor_s( x = (y, s, b) ∈ R³, state u ∈ R, control - # Box constraints (including safety constraint b >= 1e-3) + # Box constraints x(t) ≥ [0, 0, 1e-3] 0 ≤ u(t) ≤ 1 - # Initial conditions (Fixed equality) + # Initial conditions (FIXED Equality) x(t0) == [0.05, 0.5, 0.5] - # Dynamics - # Using external helper functions to avoid scope errors - ẋ[1](t) == _bio_light(t, halfperiod, μbar) * y(t) / (1 + y(t)) - (r + u(t)) * y(t) - ẋ[2](t) == -_bio_growth(s(t), μ2m, Ks) * b(t) + u(t) * β * (γ * y(t) - s(t)) - ẋ[3](t) == (_bio_growth(s(t), μ2m, Ks) - u(t) * β) * b(t) + # Dynamics (Hard-coded formulas) + ẋ[1](t) == (μbar * max(0, sin(t * π / halfperiod))^2) * y(t) / (1 + y(t)) - (r + u(t)) * y(t) + + ẋ[2](t) == -(μ2m * s(t) / (s(t) + Ks)) * b(t) + u(t) * β * (γ * y(t) - s(t)) + + ẋ[3](t) == ((μ2m * s(t) / (s(t) + Ks)) - u(t) * β) * b(t) - # Objective: Minimize negative integral (Maximize production) - -∫(_bio_growth(s(t), μ2m, Ks) * b(t) / (β + c)) → min + # Objective + -∫((μ2m * s(t) / (s(t) + Ks)) * b(t) / (β + c)) → min end # --- 3. Transcription --- From 17a478d05d176184ad4cc01e6f4ec5df35a462e1 Mon Sep 17 00:00:00 2001 From: Amiel Date: Sun, 1 Feb 2026 19:24:34 +0100 Subject: [PATCH 18/24] =?UTF-8?q?derni=C3=A8re=20chance=20!?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ext/OptimalControlModels/bioreactor.jl | 36 ++++++++++++++-------- ext/OptimalControlModels_s/bioreactor_s.jl | 22 +++++++------ 2 files changed, 35 insertions(+), 23 deletions(-) diff --git a/ext/OptimalControlModels/bioreactor.jl b/ext/OptimalControlModels/bioreactor.jl index 7212cf5d..55379af2 100644 --- a/ext/OptimalControlModels/bioreactor.jl +++ b/ext/OptimalControlModels/bioreactor.jl @@ -47,35 +47,45 @@ function OptimalControlProblems.bioreactor( s_t0_l, s_t0_u = params[:s_t0_l], params[:s_t0_u] b_t0_l, b_t0_u = params[:b_t0_l], params[:b_t0_u] + # Pre-calculate frequency to simplify the equation inside the macro + w = π / halfperiod + # --- 2. Model --- ocp = @def begin t ∈ [t0, tf], time - x = (y, s, b) ∈ R³, state + + x = (y, s, b, k) ∈ R⁴, state u ∈ R, control - # Box constraints (including safety constraint b >= 1e-3) - x(t) ≥ [0, 0, 1e-3] + # Constraints + + x(t) ≥ [0, 0, 1e-3, t0] + x(t) ≤ [Inf, Inf, Inf, tf] u_l ≤ u(t) ≤ u_u - # Initial conditions (Inequalities) - [y_t0_l, s_t0_l, b_t0_l] ≤ x(t0) ≤ [y_t0_u, s_t0_u, b_t0_u] - - # Dynamics (Hard-coded formulas to avoid scope/overwrite errors) - # Light = μbar * max(0, sin(t * π / halfperiod))^2 - # Growth = μ2m * s / (s + Ks) + + [y_t0_l, s_t0_l, b_t0_l, t0] ≤ x(t0) ≤ [y_t0_u, s_t0_u, b_t0_u, t0] - ẋ[1](t) == (μbar * max(0, sin(t * π / halfperiod))^2) * y(t) / (1 + y(t)) - (r + u(t)) * y(t) + # Dynamics + + # dy/dt + ẋ[1](t) == (μbar * max(0, sin(k(t) * w))^2) * y(t) / (1 + y(t)) - (r + u(t)) * y(t) + + # ds/dt ẋ[2](t) == -(μ2m * s(t) / (s(t) + Ks)) * b(t) + u(t) * β * (γ * y(t) - s(t)) + # db/dt ẋ[3](t) == ((μ2m * s(t) / (s(t) + Ks)) - u(t) * β) * b(t) - # Objective + + ẋ[4](t) == 1 + + -∫((μ2m * s(t) / (s(t) + Ks)) * b(t) / (β + c)) → min end - # --- 3. Transcription --- - init = (state=[0.15, 2.75, 1.75], control=0.5) + init = (state=[0.15, 2.75, 1.75, t0], control=0.5) docp = direct_transcription( ocp, diff --git a/ext/OptimalControlModels_s/bioreactor_s.jl b/ext/OptimalControlModels_s/bioreactor_s.jl index 7b7aeb50..8c6bd1b9 100644 --- a/ext/OptimalControlModels_s/bioreactor_s.jl +++ b/ext/OptimalControlModels_s/bioreactor_s.jl @@ -40,32 +40,34 @@ function OptimalControlProblems.bioreactor_s( halfperiod = params[:halfperiod] Ks, μ2m, μbar, r = params[:Ks], params[:μ2m], params[:μbar], params[:r] + w = π / halfperiod + # --- 2. Model --- ocp = @def begin t ∈ [t0, tf], time - x = (y, s, b) ∈ R³, state + x = (y, s, b, k) ∈ R⁴, state u ∈ R, control - # Box constraints - x(t) ≥ [0, 0, 1e-3] + # Constraints + x(t) ≥ [0, 0, 1e-3, t0] + x(t) ≤ [Inf, Inf, Inf, tf] 0 ≤ u(t) ≤ 1 - # Initial conditions (FIXED Equality) - x(t0) == [0.05, 0.5, 0.5] + # Fixed Initial Conditions + x(t0) == [0.05, 0.5, 0.5, t0] - # Dynamics (Hard-coded formulas) - ẋ[1](t) == (μbar * max(0, sin(t * π / halfperiod))^2) * y(t) / (1 + y(t)) - (r + u(t)) * y(t) - + # Dynamics (Using k(t) instead of t for explicit time) + ẋ[1](t) == (μbar * max(0, sin(k(t) * w))^2) * y(t) / (1 + y(t)) - (r + u(t)) * y(t) ẋ[2](t) == -(μ2m * s(t) / (s(t) + Ks)) * b(t) + u(t) * β * (γ * y(t) - s(t)) - ẋ[3](t) == ((μ2m * s(t) / (s(t) + Ks)) - u(t) * β) * b(t) + ẋ[4](t) == 1 # Objective -∫((μ2m * s(t) / (s(t) + Ks)) * b(t) / (β + c)) → min end # --- 3. Transcription --- - init = (state=[0.05, 0.5, 0.5], control=0.5) + init = (state=[0.05, 0.5, 0.5, t0], control=0.5) docp = direct_transcription( ocp, From 619b140762c32ac73270c064a95cf3066b6caa1a Mon Sep 17 00:00:00 2001 From: Amiel Date: Sun, 1 Feb 2026 19:41:36 +0100 Subject: [PATCH 19/24] adios amigos --- ext/OptimalControlModels/bioreactor.jl | 30 ++++++++++++---------- ext/OptimalControlModels_s/bioreactor_s.jl | 29 +++++++++++++-------- 2 files changed, 35 insertions(+), 24 deletions(-) diff --git a/ext/OptimalControlModels/bioreactor.jl b/ext/OptimalControlModels/bioreactor.jl index 55379af2..f4f7ce41 100644 --- a/ext/OptimalControlModels/bioreactor.jl +++ b/ext/OptimalControlModels/bioreactor.jl @@ -47,30 +47,32 @@ function OptimalControlProblems.bioreactor( s_t0_l, s_t0_u = params[:s_t0_l], params[:s_t0_u] b_t0_l, b_t0_u = params[:b_t0_l], params[:b_t0_u] - # Pre-calculate frequency to simplify the equation inside the macro - w = π / halfperiod - # --- 2. Model --- ocp = @def begin t ∈ [t0, tf], time - x = (y, s, b, k) ∈ R⁴, state u ∈ R, control - # Constraints - - x(t) ≥ [0, 0, 1e-3, t0] - x(t) ≤ [Inf, Inf, Inf, tf] + + y(t) ≥ 0 + s(t) ≥ 0 + b(t) ≥ 1e-3 + k(t) ≥ t0 + k(t) ≤ tf + + u_l ≤ u(t) ≤ u_u - [y_t0_l, s_t0_l, b_t0_l, t0] ≤ x(t0) ≤ [y_t0_u, s_t0_u, b_t0_u, t0] + y_t0_l ≤ y(t0) ≤ y_t0_u + s_t0_l ≤ s(t0) ≤ s_t0_u + b_t0_l ≤ b(t0) ≤ b_t0_u + k(t0) == t0 - # Dynamics - + # dy/dt - ẋ[1](t) == (μbar * max(0, sin(k(t) * w))^2) * y(t) / (1 + y(t)) - (r + u(t)) * y(t) + ẋ[1](t) == (μbar * max(0, sin(k(t) * π / halfperiod))^2) * y(t) / (1 + y(t)) - (r + u(t)) * y(t) # ds/dt ẋ[2](t) == -(μ2m * s(t) / (s(t) + Ks)) * b(t) + u(t) * β * (γ * y(t) - s(t)) @@ -78,13 +80,13 @@ function OptimalControlProblems.bioreactor( # db/dt ẋ[3](t) == ((μ2m * s(t) / (s(t) + Ks)) - u(t) * β) * b(t) - ẋ[4](t) == 1 - + # Objectif -∫((μ2m * s(t) / (s(t) + Ks)) * b(t) / (β + c)) → min end + # --- 3. Transcription --- init = (state=[0.15, 2.75, 1.75, t0], control=0.5) docp = direct_transcription( diff --git a/ext/OptimalControlModels_s/bioreactor_s.jl b/ext/OptimalControlModels_s/bioreactor_s.jl index 8c6bd1b9..ef7f4b30 100644 --- a/ext/OptimalControlModels_s/bioreactor_s.jl +++ b/ext/OptimalControlModels_s/bioreactor_s.jl @@ -40,29 +40,38 @@ function OptimalControlProblems.bioreactor_s( halfperiod = params[:halfperiod] Ks, μ2m, μbar, r = params[:Ks], params[:μ2m], params[:μbar], params[:r] - w = π / halfperiod - # --- 2. Model --- ocp = @def begin t ∈ [t0, tf], time x = (y, s, b, k) ∈ R⁴, state u ∈ R, control - # Constraints - x(t) ≥ [0, 0, 1e-3, t0] - x(t) ≤ [Inf, Inf, Inf, tf] + + y(t) ≥ 0 + s(t) ≥ 0 + b(t) ≥ 1e-3 + k(t) ≥ t0 + k(t) ≤ tf + 0 ≤ u(t) ≤ 1 - # Fixed Initial Conditions - x(t0) == [0.05, 0.5, 0.5, t0] + + y(t0) == 0.05 + s(t0) == 0.5 + b(t0) == 0.5 + k(t0) == t0 - # Dynamics (Using k(t) instead of t for explicit time) - ẋ[1](t) == (μbar * max(0, sin(k(t) * w))^2) * y(t) / (1 + y(t)) - (r + u(t)) * y(t) + + # dy/dt + ẋ[1](t) == (μbar * max(0, sin(k(t) * π / halfperiod))^2) * y(t) / (1 + y(t)) - (r + u(t)) * y(t) + # ds/dt ẋ[2](t) == -(μ2m * s(t) / (s(t) + Ks)) * b(t) + u(t) * β * (γ * y(t) - s(t)) + # db/dt ẋ[3](t) == ((μ2m * s(t) / (s(t) + Ks)) - u(t) * β) * b(t) + # dk/dt ẋ[4](t) == 1 - # Objective + # Objectif -∫((μ2m * s(t) / (s(t) + Ks)) * b(t) / (β + c)) → min end From f06d3403205ba1e565d1cb181830c7fec6152a12 Mon Sep 17 00:00:00 2001 From: Amiel Date: Tue, 3 Feb 2026 09:13:14 +0100 Subject: [PATCH 20/24] new test bioreactor --- ext/OptimalControlModels/bioreactor.jl | 102 ++++++++++----------- ext/OptimalControlModels_s/bioreactor_s.jl | 84 ++++++++--------- 2 files changed, 86 insertions(+), 100 deletions(-) diff --git a/ext/OptimalControlModels/bioreactor.jl b/ext/OptimalControlModels/bioreactor.jl index f4f7ce41..564acf4d 100644 --- a/ext/OptimalControlModels/bioreactor.jl +++ b/ext/OptimalControlModels/bioreactor.jl @@ -1,31 +1,9 @@ """ $(TYPEDSIGNATURES) -Constructs an **OptimalControl problem** representing the Bioreactor problem. -The function defines the state and control variables, boundary conditions, path constraints, growth and light dynamics, and an objective functional. -It performs direct transcription to create a discretised optimal control problem (DOCP) and the corresponding nonlinear programming (NLP) model. - -# Arguments - -- `::OptimalControlBackend`: Placeholder type specifying the OptimalControl backend or solver interface. -- `grid_size::Int=500`: (Keyword) Number of discretisation points for the direct transcription grid. - -# Returns - -- `docp`: The direct optimal control problem object representing the discretised Bioreactor problem. -- `nlp`: The corresponding nonlinear programming model generated from the DOCP, ready for solver input. - -# Example - -```julia-repl -julia> using OptimalControlProblems - -julia> docp = OptimalControlProblems.bioreactor(OptimalControlBackend(); N=100); -``` - -# References - -- BOCOP repository: https://github.com/control-toolbox/bocop/tree/main/bocop +Constructs an OptimalControl problem representing the Bioreactor problem. +Defines state/control variables, boundary conditions, dynamics, and objective. +Performs direct transcription to produce a DOCP model. """ function OptimalControlProblems.bioreactor( @@ -35,69 +13,81 @@ function OptimalControlProblems.bioreactor( parameters::Union{Nothing,NamedTuple}=nothing, kwargs..., ) + # --- 1. Parameters --- params = parameters_data(:bioreactor, parameters) + t0, tf = params[:t0], params[:tf] β, c, γ = params[:β], params[:c], params[:γ] halfperiod = params[:halfperiod] Ks, μ2m, μbar, r = params[:Ks], params[:μ2m], params[:μbar], params[:r] + y_l, s_l, b_l = params[:y_l], params[:s_l], params[:b_l] u_l, u_u = params[:u_l], params[:u_u] + y_t0_l, y_t0_u = params[:y_t0_l], params[:y_t0_u] s_t0_l, s_t0_u = params[:s_t0_l], params[:s_t0_u] b_t0_l, b_t0_u = params[:b_t0_l], params[:b_t0_u] - # --- 2. Model --- + # --- 2. Model definition --- ocp = @def begin t ∈ [t0, tf], time + + # Named state variables x = (y, s, b, k) ∈ R⁴, state + + # Control u ∈ R, control - + # Path constraints y(t) ≥ 0 s(t) ≥ 0 - b(t) ≥ 1e-3 - k(t) ≥ t0 - k(t) ≤ tf + b(t) ≥ 1e-3 + k(t) ≥ t0 + k(t) ≤ tf - + # Control bounds u_l ≤ u(t) ≤ u_u - - + + # Initial bounds y_t0_l ≤ y(t0) ≤ y_t0_u s_t0_l ≤ s(t0) ≤ s_t0_u b_t0_l ≤ b(t0) ≤ b_t0_u - k(t0) == t0 - - - - # dy/dt - ẋ[1](t) == (μbar * max(0, sin(k(t) * π / halfperiod))^2) * y(t) / (1 + y(t)) - (r + u(t)) * y(t) - - # ds/dt - ẋ[2](t) == -(μ2m * s(t) / (s(t) + Ks)) * b(t) + u(t) * β * (γ * y(t) - s(t)) - - # db/dt - ẋ[3](t) == ((μ2m * s(t) / (s(t) + Ks)) - u(t) * β) * b(t) - - ẋ[4](t) == 1 - - # Objectif + k(t0) == t0 + + # Smooth light growth term (AD-friendly) + light = sin(k(t) * π / halfperiod)^2 + + # Dynamics (named derivatives required by DSL) + ẏ(t) == (μbar * light) * y(t) / (1 + y(t)) - (r + u(t)) * y(t) + + ṡ(t) == -(μ2m * s(t) / (s(t) + Ks)) * b(t) + + u(t) * β * (γ * y(t) - s(t)) + + ḃ(t) == ((μ2m * s(t) / (s(t) + Ks)) - u(t) * β) * b(t) + + ḱ(t) == 1 + + # Objective -∫((μ2m * s(t) / (s(t) + Ks)) * b(t) / (β + c)) → min end - # --- 3. Transcription --- - init = (state=[0.15, 2.75, 1.75, t0], control=0.5) + # --- 3. Initial guess --- + init = ( + state = [0.15, 2.75, 1.75, t0], + control = 0.5, + ) + # --- 4. Direct transcription --- docp = direct_transcription( ocp, description...; - lagrange_to_mayer=false, - init=init, - grid_size=grid_size, - disc_method=:trapeze, + lagrange_to_mayer = false, + init = init, + grid_size = grid_size, + disc_method = :trapezoid, kwargs..., ) return docp -end \ No newline at end of file +end diff --git a/ext/OptimalControlModels_s/bioreactor_s.jl b/ext/OptimalControlModels_s/bioreactor_s.jl index ef7f4b30..ea98f093 100644 --- a/ext/OptimalControlModels_s/bioreactor_s.jl +++ b/ext/OptimalControlModels_s/bioreactor_s.jl @@ -1,29 +1,11 @@ """ $(TYPEDSIGNATURES) -Constructs an **OptimalControl problem** representing the **Bioreactor problem** with **fixed initial conditions**. -The function sets up the state variables (algae , substrate , biomass ), the control variable (flow rate ), and the specific dynamics governing the photobioreactor-digester coupling. +Constructs an OptimalControl problem representing the Bioreactor problem +with fixed initial conditions. -Unlike the general case, this version (`_s`) fixes the initial state to a specific point x(0) = [0.05, 0.5, 0.5] and enforces a safety constraint b(t) ge 10^{-3} to prevent biomass washout. - -It performs direct transcription to generate a discrete optimal control problem (DOCP). - -# Arguments - -- `::OptimalControlBackend`: Placeholder type specifying the OptimalControl backend or solver interface. -- `grid_size::Int=grid_size_data(:bioreactor)`: (Keyword) Number of discretisation points for the direct transcription grid. - -# Returns - -- `docp`: The direct optimal control problem object representing the discretised Bioreactor problem. - -# Example - -```julia-repl -julia> using OptimalControlProblems - -julia> docp = OptimalControlProblems.bioreactor(OptimalControlBackend(); N=100); -``` +This version fixes the initial state and enforces a biomass safety bound. +Direct transcription is applied to build the DOCP. """ function OptimalControlProblems.bioreactor_s( @@ -33,60 +15,74 @@ function OptimalControlProblems.bioreactor_s( parameters::Union{Nothing,NamedTuple}=nothing, kwargs..., ) + # --- 1. Parameters --- params = parameters_data(:bioreactor, parameters) + t0, tf = params[:t0], params[:tf] β, c, γ = params[:β], params[:c], params[:γ] halfperiod = params[:halfperiod] Ks, μ2m, μbar, r = params[:Ks], params[:μ2m], params[:μbar], params[:r] - # --- 2. Model --- + # --- 2. Model definition --- ocp = @def begin t ∈ [t0, tf], time + + # Named state variables x = (y, s, b, k) ∈ R⁴, state + + # Control u ∈ R, control - + # Path constraints y(t) ≥ 0 s(t) ≥ 0 b(t) ≥ 1e-3 k(t) ≥ t0 k(t) ≤ tf - + + # Control bounds 0 ≤ u(t) ≤ 1 - + # Fixed initial conditions y(t0) == 0.05 s(t0) == 0.5 b(t0) == 0.5 k(t0) == t0 - - # dy/dt - ẋ[1](t) == (μbar * max(0, sin(k(t) * π / halfperiod))^2) * y(t) / (1 + y(t)) - (r + u(t)) * y(t) - # ds/dt - ẋ[2](t) == -(μ2m * s(t) / (s(t) + Ks)) * b(t) + u(t) * β * (γ * y(t) - s(t)) - # db/dt - ẋ[3](t) == ((μ2m * s(t) / (s(t) + Ks)) - u(t) * β) * b(t) - # dk/dt - ẋ[4](t) == 1 - - # Objectif + # Smooth light term (AD-safe) + light = sin(k(t) * π / halfperiod)^2 + + # Dynamics using named derivatives + ẏ(t) == (μbar * light) * y(t) / (1 + y(t)) - (r + u(t)) * y(t) + + ṡ(t) == -(μ2m * s(t) / (s(t) + Ks)) * b(t) + + u(t) * β * (γ * y(t) - s(t)) + + ḃ(t) == ((μ2m * s(t) / (s(t) + Ks)) - u(t) * β) * b(t) + + ḱ(t) == 1 + + # Objective functional -∫((μ2m * s(t) / (s(t) + Ks)) * b(t) / (β + c)) → min end - # --- 3. Transcription --- - init = (state=[0.05, 0.5, 0.5, t0], control=0.5) + # --- 3. Initial guess --- + init = ( + state = [0.05, 0.5, 0.5, t0], + control = 0.5, + ) + # --- 4. Direct transcription --- docp = direct_transcription( ocp, description...; - lagrange_to_mayer=false, - init=init, - grid_size=grid_size, - disc_method=:trapeze, + lagrange_to_mayer = false, + init = init, + grid_size = grid_size, + disc_method = :trapezoid, kwargs..., ) return docp -end \ No newline at end of file +end From a4f2aca0ca1a68ee18137912501e14b415237321 Mon Sep 17 00:00:00 2001 From: Amiel Date: Tue, 3 Feb 2026 09:19:04 +0100 Subject: [PATCH 21/24] po --- ext/OptimalControlModels/bioreactor.jl | 58 ++++++++++------------ ext/OptimalControlModels_s/bioreactor_s.jl | 54 +++++++++----------- 2 files changed, 50 insertions(+), 62 deletions(-) diff --git a/ext/OptimalControlModels/bioreactor.jl b/ext/OptimalControlModels/bioreactor.jl index 564acf4d..d7d16964 100644 --- a/ext/OptimalControlModels/bioreactor.jl +++ b/ext/OptimalControlModels/bioreactor.jl @@ -1,20 +1,17 @@ """ -$(TYPEDSIGNATURES) - -Constructs an OptimalControl problem representing the Bioreactor problem. -Defines state/control variables, boundary conditions, dynamics, and objective. -Performs direct transcription to produce a DOCP model. +Constructs an OptimalControl bioreactor model. +Vector state form is required by CTParser. """ function OptimalControlProblems.bioreactor( ::OptimalControlBackend, description::Symbol...; - grid_size::Int=grid_size_data(:bioreactor), - parameters::Union{Nothing,NamedTuple}=nothing, + grid_size::Int = grid_size_data(:bioreactor), + parameters::Union{Nothing,NamedTuple} = nothing, kwargs..., ) - # --- 1. Parameters --- + # --- Parameters --- params = parameters_data(:bioreactor, parameters) t0, tf = params[:t0], params[:tf] @@ -29,56 +26,53 @@ function OptimalControlProblems.bioreactor( s_t0_l, s_t0_u = params[:s_t0_l], params[:s_t0_u] b_t0_l, b_t0_u = params[:b_t0_l], params[:b_t0_u] - # --- 2. Model definition --- + # --- Model --- ocp = @def begin t ∈ [t0, tf], time - # Named state variables - x = (y, s, b, k) ∈ R⁴, state - - # Control + # Vector state required by parser + x ∈ R⁴, state u ∈ R, control - # Path constraints + # State aliases for readability + y = x[1] + s = x[2] + b = x[3] + k = x[4] + + # Constraints y(t) ≥ 0 s(t) ≥ 0 b(t) ≥ 1e-3 k(t) ≥ t0 k(t) ≤ tf - # Control bounds u_l ≤ u(t) ≤ u_u - # Initial bounds y_t0_l ≤ y(t0) ≤ y_t0_u s_t0_l ≤ s(t0) ≤ s_t0_u b_t0_l ≤ b(t0) ≤ b_t0_u k(t0) == t0 - # Smooth light growth term (AD-friendly) + # Smooth light term light = sin(k(t) * π / halfperiod)^2 - # Dynamics (named derivatives required by DSL) - ẏ(t) == (μbar * light) * y(t) / (1 + y(t)) - (r + u(t)) * y(t) - - ṡ(t) == -(μ2m * s(t) / (s(t) + Ks)) * b(t) + - u(t) * β * (γ * y(t) - s(t)) - - ḃ(t) == ((μ2m * s(t) / (s(t) + Ks)) - u(t) * β) * b(t) - - ḱ(t) == 1 + # Vector dynamics (required form) + ẋ(t) == [ + (μbar * light) * y(t) / (1 + y(t)) - (r + u(t)) * y(t), + -(μ2m * s(t) / (s(t) + Ks)) * b(t) + u(t) * β * (γ * y(t) - s(t)), + ((μ2m * s(t) / (s(t) + Ks)) - u(t) * β) * b(t), + 1 + ] # Objective -∫((μ2m * s(t) / (s(t) + Ks)) * b(t) / (β + c)) → min end - # --- 3. Initial guess --- - init = ( - state = [0.15, 2.75, 1.75, t0], - control = 0.5, - ) + # --- Initial guess --- + init = (state = [0.15, 2.75, 1.75, t0], control = 0.5) - # --- 4. Direct transcription --- + # --- Transcription --- docp = direct_transcription( ocp, description...; diff --git a/ext/OptimalControlModels_s/bioreactor_s.jl b/ext/OptimalControlModels_s/bioreactor_s.jl index ea98f093..f07eb6e0 100644 --- a/ext/OptimalControlModels_s/bioreactor_s.jl +++ b/ext/OptimalControlModels_s/bioreactor_s.jl @@ -1,22 +1,17 @@ """ -$(TYPEDSIGNATURES) - -Constructs an OptimalControl problem representing the Bioreactor problem -with fixed initial conditions. - -This version fixes the initial state and enforces a biomass safety bound. -Direct transcription is applied to build the DOCP. +Constructs an OptimalControl bioreactor model with fixed initial conditions. +Vector state form is required by CTParser. """ function OptimalControlProblems.bioreactor_s( ::OptimalControlBackend, description::Symbol...; - grid_size::Int=grid_size_data(:bioreactor), - parameters::Union{Nothing,NamedTuple}=nothing, + grid_size::Int = grid_size_data(:bioreactor), + parameters::Union{Nothing,NamedTuple} = nothing, kwargs..., ) - # --- 1. Parameters --- + # --- Parameters --- params = parameters_data(:bioreactor, parameters) t0, tf = params[:t0], params[:tf] @@ -24,16 +19,20 @@ function OptimalControlProblems.bioreactor_s( halfperiod = params[:halfperiod] Ks, μ2m, μbar, r = params[:Ks], params[:μ2m], params[:μbar], params[:r] - # --- 2. Model definition --- + # --- Model --- ocp = @def begin t ∈ [t0, tf], time - # Named state variables - x = (y, s, b, k) ∈ R⁴, state - - # Control + # Vector state required by parser + x ∈ R⁴, state u ∈ R, control + # State aliases for readability + y = x[1] + s = x[2] + b = x[3] + k = x[4] + # Path constraints y(t) ≥ 0 s(t) ≥ 0 @@ -53,27 +52,22 @@ function OptimalControlProblems.bioreactor_s( # Smooth light term (AD-safe) light = sin(k(t) * π / halfperiod)^2 - # Dynamics using named derivatives - ẏ(t) == (μbar * light) * y(t) / (1 + y(t)) - (r + u(t)) * y(t) - - ṡ(t) == -(μ2m * s(t) / (s(t) + Ks)) * b(t) + - u(t) * β * (γ * y(t) - s(t)) - - ḃ(t) == ((μ2m * s(t) / (s(t) + Ks)) - u(t) * β) * b(t) - - ḱ(t) == 1 + # Vector dynamics + ẋ(t) == [ + (μbar * light) * y(t) / (1 + y(t)) - (r + u(t)) * y(t), + -(μ2m * s(t) / (s(t) + Ks)) * b(t) + u(t) * β * (γ * y(t) - s(t)), + ((μ2m * s(t) / (s(t) + Ks)) - u(t) * β) * b(t), + 1 + ] # Objective functional -∫((μ2m * s(t) / (s(t) + Ks)) * b(t) / (β + c)) → min end - # --- 3. Initial guess --- - init = ( - state = [0.05, 0.5, 0.5, t0], - control = 0.5, - ) + # --- Initial guess --- + init = (state = [0.05, 0.5, 0.5, t0], control = 0.5) - # --- 4. Direct transcription --- + # --- Direct transcription --- docp = direct_transcription( ocp, description...; From c1fab4f87dc9f4bbb1c2dd760169df11ddb618fc Mon Sep 17 00:00:00 2001 From: Amiel Date: Tue, 3 Feb 2026 09:20:17 +0100 Subject: [PATCH 22/24] add space shuttle --- src/OptimalControlProblems.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/OptimalControlProblems.jl b/src/OptimalControlProblems.jl index d13dd18b..806e4f79 100644 --- a/src/OptimalControlProblems.jl +++ b/src/OptimalControlProblems.jl @@ -69,7 +69,7 @@ function make_list_of_problems() :moonlander, :ducted_fan, :robot, - :space_shuttle, + #:space_shuttle, ] list_of_problems = setdiff(list_of_problems, problems_to_exclude) From 9c760589a447e2a612937aae6cbaa9f7fa623764 Mon Sep 17 00:00:00 2001 From: Amiel Date: Tue, 3 Feb 2026 09:45:46 +0100 Subject: [PATCH 23/24] jean christophe --- ext/OptimalControlModels/bioreactor.jl | 51 +++++++++++----------- ext/OptimalControlModels_s/bioreactor_s.jl | 41 +++++++++-------- src/OptimalControlProblems.jl | 2 +- 3 files changed, 47 insertions(+), 47 deletions(-) diff --git a/ext/OptimalControlModels/bioreactor.jl b/ext/OptimalControlModels/bioreactor.jl index d7d16964..274e8e64 100644 --- a/ext/OptimalControlModels/bioreactor.jl +++ b/ext/OptimalControlModels/bioreactor.jl @@ -1,27 +1,23 @@ """ -Constructs an OptimalControl bioreactor model. -Vector state form is required by CTParser. -""" +$(TYPEDSIGNATURES) +Constructs the **Bioreactor optimal control problem** (Autonomous formulation). +""" function OptimalControlProblems.bioreactor( ::OptimalControlBackend, description::Symbol...; - grid_size::Int = grid_size_data(:bioreactor), - parameters::Union{Nothing,NamedTuple} = nothing, + grid_size::Int=grid_size_data(:bioreactor), + parameters::Union{Nothing,NamedTuple}=nothing, kwargs..., ) - # --- Parameters --- params = parameters_data(:bioreactor, parameters) - t0, tf = params[:t0], params[:tf] β, c, γ = params[:β], params[:c], params[:γ] halfperiod = params[:halfperiod] Ks, μ2m, μbar, r = params[:Ks], params[:μ2m], params[:μbar], params[:r] - y_l, s_l, b_l = params[:y_l], params[:s_l], params[:b_l] u_l, u_u = params[:u_l], params[:u_u] - y_t0_l, y_t0_u = params[:y_t0_l], params[:y_t0_u] s_t0_l, s_t0_u = params[:s_t0_l], params[:s_t0_u] b_t0_l, b_t0_u = params[:b_t0_l], params[:b_t0_u] @@ -29,41 +25,46 @@ function OptimalControlProblems.bioreactor( # --- Model --- ocp = @def begin t ∈ [t0, tf], time - - # Vector state required by parser + + # Vector state required by parser (4th component k is time) x ∈ R⁴, state u ∈ R, control - # State aliases for readability + # Coordinate aliases for readability y = x[1] s = x[2] b = x[3] k = x[4] - # Constraints + # Path constraints y(t) ≥ 0 s(t) ≥ 0 b(t) ≥ 1e-3 k(t) ≥ t0 k(t) ≤ tf + # Control bounds u_l ≤ u(t) ≤ u_u + # Initial bounds y_t0_l ≤ y(t0) ≤ y_t0_u s_t0_l ≤ s(t0) ≤ s_t0_u b_t0_l ≤ b(t0) ≤ b_t0_u k(t0) == t0 - # Smooth light term - light = sin(k(t) * π / halfperiod)^2 + # Dynamics (Coordinatewise & Inline calculation for light) + + # dy/dt: We inline the light calculation: sin(k(t) * π / halfperiod)^2 + ẋ[1](t) == (μbar * sin(k(t) * π / halfperiod)^2) * y(t) / (1 + y(t)) - (r + u(t)) * y(t) + + # ds/dt + ẋ[2](t) == -(μ2m * s(t) / (s(t) + Ks)) * b(t) + u(t) * β * (γ * y(t) - s(t)) + + # db/dt + ẋ[3](t) == ((μ2m * s(t) / (s(t) + Ks)) - u(t) * β) * b(t) - # Vector dynamics (required form) - ẋ(t) == [ - (μbar * light) * y(t) / (1 + y(t)) - (r + u(t)) * y(t), - -(μ2m * s(t) / (s(t) + Ks)) * b(t) + u(t) * β * (γ * y(t) - s(t)), - ((μ2m * s(t) / (s(t) + Ks)) - u(t) * β) * b(t), - 1 - ] + # dk/dt (Time clock) + ẋ[4](t) == 1 # Objective -∫((μ2m * s(t) / (s(t) + Ks)) * b(t) / (β + c)) → min @@ -72,16 +73,16 @@ function OptimalControlProblems.bioreactor( # --- Initial guess --- init = (state = [0.15, 2.75, 1.75, t0], control = 0.5) - # --- Transcription --- + # --- Direct transcription --- docp = direct_transcription( ocp, description...; lagrange_to_mayer = false, init = init, grid_size = grid_size, - disc_method = :trapezoid, + disc_method = :trapeze, # CORRECTION: :trapeze, not :trapezoid kwargs..., ) return docp -end +end \ No newline at end of file diff --git a/ext/OptimalControlModels_s/bioreactor_s.jl b/ext/OptimalControlModels_s/bioreactor_s.jl index f07eb6e0..9d08e4df 100644 --- a/ext/OptimalControlModels_s/bioreactor_s.jl +++ b/ext/OptimalControlModels_s/bioreactor_s.jl @@ -1,8 +1,8 @@ """ -Constructs an OptimalControl bioreactor model with fixed initial conditions. -Vector state form is required by CTParser. -""" +$(TYPEDSIGNATURES) +Constructs the **Bioreactor optimal control problem** with **fixed initial conditions**. +""" function OptimalControlProblems.bioreactor_s( ::OptimalControlBackend, description::Symbol...; @@ -10,10 +10,8 @@ function OptimalControlProblems.bioreactor_s( parameters::Union{Nothing,NamedTuple} = nothing, kwargs..., ) - # --- Parameters --- params = parameters_data(:bioreactor, parameters) - t0, tf = params[:t0], params[:tf] β, c, γ = params[:β], params[:c], params[:γ] halfperiod = params[:halfperiod] @@ -22,12 +20,10 @@ function OptimalControlProblems.bioreactor_s( # --- Model --- ocp = @def begin t ∈ [t0, tf], time - - # Vector state required by parser x ∈ R⁴, state u ∈ R, control - # State aliases for readability + # Coordinate aliases y = x[1] s = x[2] b = x[3] @@ -43,24 +39,27 @@ function OptimalControlProblems.bioreactor_s( # Control bounds 0 ≤ u(t) ≤ 1 - # Fixed initial conditions + # Fixed Initial Conditions y(t0) == 0.05 s(t0) == 0.5 b(t0) == 0.5 k(t0) == t0 - # Smooth light term (AD-safe) - light = sin(k(t) * π / halfperiod)^2 + # Dynamics (Coordinatewise & Inline) + + # dy/dt + ẋ[1](t) == (μbar * sin(k(t) * π / halfperiod)^2) * y(t) / (1 + y(t)) - (r + u(t)) * y(t) + + # ds/dt + ẋ[2](t) == -(μ2m * s(t) / (s(t) + Ks)) * b(t) + u(t) * β * (γ * y(t) - s(t)) + + # db/dt + ẋ[3](t) == ((μ2m * s(t) / (s(t) + Ks)) - u(t) * β) * b(t) - # Vector dynamics - ẋ(t) == [ - (μbar * light) * y(t) / (1 + y(t)) - (r + u(t)) * y(t), - -(μ2m * s(t) / (s(t) + Ks)) * b(t) + u(t) * β * (γ * y(t) - s(t)), - ((μ2m * s(t) / (s(t) + Ks)) - u(t) * β) * b(t), - 1 - ] + # dk/dt + ẋ[4](t) == 1 - # Objective functional + # Objective -∫((μ2m * s(t) / (s(t) + Ks)) * b(t) / (β + c)) → min end @@ -74,9 +73,9 @@ function OptimalControlProblems.bioreactor_s( lagrange_to_mayer = false, init = init, grid_size = grid_size, - disc_method = :trapezoid, + disc_method = :trapeze, kwargs..., ) return docp -end +end \ No newline at end of file diff --git a/src/OptimalControlProblems.jl b/src/OptimalControlProblems.jl index 806e4f79..8de6fcd5 100644 --- a/src/OptimalControlProblems.jl +++ b/src/OptimalControlProblems.jl @@ -68,7 +68,7 @@ function make_list_of_problems() :dielectrophoretic_particle, :moonlander, :ducted_fan, - :robot, + #:robot, #:space_shuttle, ] list_of_problems = setdiff(list_of_problems, problems_to_exclude) From 22d8221d401978ff9a4c46f22d21f158d630c669 Mon Sep 17 00:00:00 2001 From: Amiel Date: Tue, 3 Feb 2026 10:22:18 +0100 Subject: [PATCH 24/24] remove bio --- src/OptimalControlProblems.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/OptimalControlProblems.jl b/src/OptimalControlProblems.jl index 8de6fcd5..9cd2d443 100644 --- a/src/OptimalControlProblems.jl +++ b/src/OptimalControlProblems.jl @@ -63,7 +63,7 @@ function make_list_of_problems() # exclude the following problems problems_to_exclude = [ - #:bioreactor, + :bioreactor, :cart_pendulum, :dielectrophoretic_particle, :moonlander,