Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Preparing for inplace NLP #232

Closed
jbcaillau opened this issue Aug 9, 2024 · 17 comments · Fixed by #271
Closed

Preparing for inplace NLP #232

jbcaillau opened this issue Aug 9, 2024 · 17 comments · Fixed by #271
Assignees
Labels
enhancement New feature or request internal dev Modification to the code is requested and should not affect user experiment

Comments

@jbcaillau
Copy link
Member

jbcaillau commented Aug 9, 2024

@PierreMartinon aiming to providing inplace function as a result of nlp_constraints!, having inplace signatures for ξ, η, ψ, ϕ, θ:

julia> (ξl, ξ, ξu), (ηl, η, ηu), (ψl, ψ, ψu), (ϕl, ϕ, ϕu), (θl, θ, θu),
    (ul, uind, uu), (xl, xind, xu), (vl, vind, vu) = nlp_constraints!(ocp)

Related to: control-toolbox/CTDirect.jl#188

@ocots I'll need some help to update the unit tests.

@jbcaillau
Copy link
Member Author

jbcaillau commented Aug 9, 2024

@jbcaillau To update:

In model.jl

5 possible nonlinear (= defined by functions, now inplace) constraints to treat, associated respectively with ξ, η, ψ, ϕ, θ:

        (type, f::BoundaryConstraint, lb, ub) && if type  [:initial, :final, :boundary] end # ϕ
        (:control, f::ControlConstraint, lb, ub) # ξ
        (:state, f::StateConstraint, lb, ub) # η
        (:mixed, f::MixedConstraint, lb, ub) # ψ
        (:variable, f::VariableConstraint, lb, ub) # θ

Also (see fun_range):

function constraint!(
    ocp::OptimalControlModel{T, V}, 
    type::Symbol;
    rg::Union{OrdinalRange{<:Integer}, Index, Integer, Nothing}=nothing, 
    f::Union{Function, Nothing}=nothing, 
    lb::Union{ctVector, Nothing}=nothing, 
    ub::Union{ctVector, Nothing}=nothing,
    val::Union{ctVector, Nothing}=nothing,
    label::Symbol=__constraint_label()) where {T <: TimeDependence, V <: VariableDependence}

Also:

function constraint(ocp::OptimalControlModel{T, V}, label::Symbol) where {T <: TimeDependence, V <: VariableDependence}

In onepass.jl

p_constraint!(p, ocp, e1, e2, e3, label=gensym(); log=false)
p_dynamics!(p, ocp, x, t, e, label=nothing; log=false)
p_lagrange!(p, ocp, e, type; log=false)
p_mayer!(p, ocp, e, type; log=false)
p_bolza!(p, ocp, e1, e2, type; log=false)

NB.

  • use function for long funs (blue style)
  • code = then __wrap(code, p.lnum, p.line) in every p_...
  • even better(?): factor out generated code for alternative future generated code

Misc

  • check allocations with @allocates
  • use views, see 232 preparing for inplace nlp #271 (comment)
  • is_in_place(ocp) now available
  • if false (default for functional syntax), nothing changed
  • should always be true for abstract, ensuring to map problems towards efficient functional code
  • first (maybe useless thanks to second step): add in-place functions from abstract, but cheat ocp getters to provide out of place and pass the tests as before, and build in CTDirect.jl and before
  • second: cheat getters in tests to return out of place funs (while in place will be passed)
  • end: remove all this

Type changes

  • also Dynamics, Lagrange, Mayer (in addition to the 5 nonlinear constraint types)
  • Type -> Type_ for all optimal_control_model-setters
  • enrich union type in the ocp model
  • add
Mayer_(ocp, f_::Function; variable::Bool = false) = is_in_place(ocp) ? Mayer!(f_; variable) : Mayer(f_; variable)
  • NB : actually, Mayer_ = is_in_place(ocp) ? Mayer! : Mayer also works
  • check all getters/setters for types

@jbcaillau
Copy link
Member Author

@PierreMartinon any preliminary comments?

@PierreMartinon aiming to providing inplace function as a result of nlp_constraints!, having inplace signatures for ξ, η, ψ, ϕ, θ:

julia> (ξl, ξ, ξu), (ηl, η, ηu), (ψl, ψ, ψu), (ϕl, ϕ, ϕu), (θl, θ, θu),
    (ul, uind, uu), (xl, xind, xu), (vl, vind, vu) = nlp_constraints!(ocp)

Related to: control-toolbox/CTDirect.jl#188

@ocots ocots added enhancement New feature or request internal dev Modification to the code is requested and should not affect user experiment labels Aug 22, 2024
@jbcaillau
Copy link
Member Author

jbcaillau commented Aug 29, 2024

@PierreMartinon back on this issue. on your side, ready for inplace in CTDirect.jl with trapezoidal scheme? Target above: #232 (comment)

@jbcaillau
Copy link
Member Author

@ocots I'll need some help to update the unit tests.

@ocots we'll need to be able to run tests like

    @def o begin
        t  [ 0, 1 ], time
        x = [ r, v ]  R², state
        u  R, control
        w = r + 2v
        r(0) == 0,    (1)
        v(0) == 1,    (♡)
        (t) == [ v(t), w(t)^2 ]
        ( u(t)^2 + x₁(t) )  min
    end
    x = [ 1, 2 ]
    x0  = 2 * x
    xf  = 3 * x
    u = 3
    @test constraint(o, :eq1)(x0, xf) == x0[1]
    @test constraint(o, Symbol(""))(x0, xf) == x0[2]
    @test o.dynamics(x, u) == [ x[2], (x[1] + 2x[2])^2 ]
    @test o.lagrange(x, u) == u^2 + x[1]

It is better not to rewrite test but to update the getters (such as constraint) so that they take care of the functions now being in place. My question: can you please remind me what getters are available for dynamics and the three different costs? (Using getters in the test would be nicer, too.)

@ocots
Copy link
Member

ocots commented Aug 29, 2024

Getters:

lagrange(ocp::OptimalControlModel) = ocp.lagrange
"""
$(TYPEDSIGNATURES)
Return the Mayer part of the cost of the optimal control problem or `nothing`.
"""
mayer(ocp::OptimalControlModel) = ocp.mayer
"""
$(TYPEDSIGNATURES)
Return the criterion (`:min` or `:max`) of the optimal control problem or `nothing`.
"""
criterion(ocp::OptimalControlModel) = ocp.criterion
"""
$(TYPEDSIGNATURES)
Return the dynamics of the optimal control problem or `nothing`.
"""
dynamics(ocp::OptimalControlModel) = ocp.dynamics

@jbcaillau
Copy link
Member Author

@ocots excellent. do think you could vscode update test_onepass.jl to replace field accesses by these getters? Then it should be fairly easy to reuse the existing tests with in place functions.

@jbcaillau
Copy link
Member Author

jbcaillau commented Aug 30, 2024

Getters:
[...]

@ocots just for the record: no bolza getter, subsumed by lagrange + mayer ones, I suppose? YES

@PierreMartinon
Copy link
Member

Hi guys,
While you're at it, can you make it so that initial conditions are always before final conditions when building the boundary conditions ?
Also, iirc mayer exists only in autonomous version ?

@jbcaillau
Copy link
Member Author

jbcaillau commented Aug 31, 2024

@PierreMartinon

Hi guys, While you're at it, can you make it so that initial conditions are always before final conditions when building the boundary conditions ?

OK

Also, iirc mayer exists only in autonomous version ?

Not sure that the question makes sense:

  • either $t_0$ and $t_f$ are fixed and the mayer cost function is $g(x_0,x_f[,v])$ (where $v$ might be a variable)
  • or $t_f$, for instance, is free and then is (a component of) the variable, so $g(x_0, x_f, t_f)$ is expected

Same thing for (nonlinear) boundary conditions, BTW.

Am I missing sth?

@jbcaillau
Copy link
Member Author

@PierreMartinon meeting tomorrow (tuesday) 14:00
https://inria.webex.com/meet/jean-baptiste.caillau

@ocots @joseph-gergaud welcome to join if you're around!

@ocots
Copy link
Member

ocots commented Sep 3, 2024

@PierreMartinon Parametric type:

struct TypeParamExample{T<:Number}
    x::T
end

and for a function:

julia> function f(x::T, y::T) where {T <: Number}
       return x + y
       end
f (generic function with 1 method)

julia> f(1, 2)
3

julia> f(1, 2.0)
ERROR: MethodError: no method matching f(::Int64, ::Float64)

Closest candidates are:
  f(::T, ::T) where T<:Number
   @ Main REPL[5]:1

Stacktrace:
 [1] top-level scope
   @ REPL[7]:1

@joseph-gergaud
Copy link
Member

@jbcaillau
The scalar case for the constraints must be treated.

@ocots
Copy link
Member

ocots commented Sep 3, 2024

@PierreMartinon Voir :

@jbcaillau
Copy link
Member Author

@jbcaillau The scalar case for the constraints must be treated.

@joseph-gergaud @PierreMartinon should be OK provided in place functions returned by nlp_constraints! are called with a (slice of) vector as first arg. may be an exception for Lagrange cost, to be checked. in any case, the possible generated error should be clear enough 🤞🏾

@jbcaillau
Copy link
Member Author

jbcaillau commented Sep 6, 2024

  •  @jbcaillau adapt getters (constraint, dynamics, lagrange, mayer) to transform in place into out of place inside unitary tests
  • impacted tests:
    • test_onepass
    • test_model (useless)

@jbcaillau
Copy link
Member Author

@PierreMartinon catch-up this Monday 9/9 at 14:00 on zoom
https://univ-cotedazur.zoom.us/my/caillau

@ocots @joseph-gergaud welcome if you're around!

@jbcaillau
Copy link
Member Author

Hi guys, While you're at it, can you make it so that initial conditions are always before final conditions when building the boundary conditions ? Also, iirc mayer exists only in autonomous version ?

@PierreMartinon closing this issue, in favour of #288 (please answer there!)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request internal dev Modification to the code is requested and should not affect user experiment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants