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

Update basic example tutorial functional syntax #264

Open
ocots opened this issue Aug 5, 2024 · 14 comments · Fixed by #274
Open

Update basic example tutorial functional syntax #264

ocots opened this issue Aug 5, 2024 · 14 comments · Fixed by #274
Assignees
Labels
documentation Improvements or additions to documentation

Comments

@ocots
Copy link
Member

ocots commented Aug 5, 2024

          When done, update https://control-toolbox.org/OptimalControl.jl/stable/tutorial-basic-example-f.html.

Originally posted by @ocots in control-toolbox/CTBase.jl#204 (comment)

@ocots ocots added the documentation Improvements or additions to documentation label Aug 5, 2024
@ocots ocots linked a pull request Aug 8, 2024 that will close this issue
@ocots ocots closed this as completed in #274 Aug 8, 2024
@paolo-mgi
Copy link

Would it be possible to add the functional syntax also to the time minimisation problem?
Many thanks

@ocots
Copy link
Member Author

ocots commented Aug 9, 2024

Would it be possible to add the functional syntax also to the time minimisation problem? Many thanks

Ok I will add it.

We are interested by your feedback. Do you prefer to use the functional syntax rather than the abstract syntax? Could you explain why?

@paolo-mgi
Copy link

Many thanks!

The main reason is that I feel that being able to use both syntaxes gives a better understanding of how the package is working.

Clearly there is something I am not understanding at the moment. Based on the basic example and the API I tried to rewrite the time minimization but I got an error indicatiing that I haven't defined correctly tf (abstract syntax works as expected instead).

Another reaon is that I am used to write notebooks with nteract where latex rendering is somewhat cumbersome (no tab completion). Probably I should move to Pluto but I have some inertia...

Thanks again for the swift reply and the very nice work!

@ocots
Copy link
Member Author

ocots commented Aug 9, 2024

I was not aware of nteract. I write notebooks with vscode and in this case, you can easily write special characters.

In the next release, there will be a tutorial about the abstract syntax.

One can find some infos about the API of the Model function but it is not well indicated.

@ocots
Copy link
Member Author

ocots commented Aug 12, 2024

Pin @jbcaillau.

@jbcaillau
Copy link
Member

Hi @paolo-mgi thanks for the feedback. As indicated by @ocots the doc for abstract syntax is now available n dev and in a few hours 🤞🏾in the next release of OptimalControl.jl.

More specifically, regarding your points:

  • we're adding non unicode keywords so everything should fine, even within the abstract syntax
    Add non unicode keywords CTBase.jl#239
  • you can always have a look at the generated functional code to guess, from the abstract form, what was needed (see example below)
julia> @macroexpand @def ocp begin

           tf  R,          variable
           t  [ 0, tf ],   time
           x = (q, v)  R², state
           u  R,           control

           tf  0
           -1  u(t)  1

           q(0)  == 1
           v(0)  == 2
           q(tf) == 0
           v(tf) == 0

            0  q(t)  5,          (1)
           -2  v(t)  3,          (2)

           (t) == [ v(t), u(t) ]

           tf  min

       end
quote
    ocp = __OCPModel(variable = true)
    begin
        #= REPL[5]:3 =#
        begin
            #= /home/jcaillau/.julia/packages/CTBase/fDnnG/src/onepass.jl:46 =#
            local ex
            #= /home/jcaillau/.julia/packages/CTBase/fDnnG/src/onepass.jl:47 =#
            try
                #= /home/jcaillau/.julia/packages/CTBase/fDnnG/src/onepass.jl:48 =#
                variable!(ocp, 1, :tf)
            catch ex
                #= /home/jcaillau/.julia/packages/CTBase/fDnnG/src/onepass.jl:50 =#
                println("Line ", 1, ": ", "(tf ∈ R, variable)")
                #= /home/jcaillau/.julia/packages/CTBase/fDnnG/src/onepass.jl:51 =#
                throw(ex)
            end
        end
        #= REPL[5]:4 =#
        begin
            #= /home/jcaillau/.julia/packages/CTBase/fDnnG/src/onepass.jl:46 =#
            local ex
            #= /home/jcaillau/.julia/packages/CTBase/fDnnG/src/onepass.jl:47 =#
            try
                #= /home/jcaillau/.julia/packages/CTBase/fDnnG/src/onepass.jl:48 =#
                begin
                    #= /home/jcaillau/.julia/packages/CTBase/fDnnG/src/onepass.jl:213 =#
                    ocp.variable_dimension  1 && throw(IncorrectArgument("variable must be of dimension one for a time"))
                    #= /home/jcaillau/.julia/packages/CTBase/fDnnG/src/onepass.jl:215 =#
                    time!(ocp; t0 = 0, indf = 1, name = :t)
                end
            catch ex
                #= /home/jcaillau/.julia/packages/CTBase/fDnnG/src/onepass.jl:50 =#
                println("Line ", 2, ": ", "(t ∈ [0, tf], time)")
                #= /home/jcaillau/.julia/packages/CTBase/fDnnG/src/onepass.jl:51 =#
                throw(ex)
            end
        end
        #= REPL[5]:5 =#
        begin
            #= /home/jcaillau/.julia/packages/CTBase/fDnnG/src/onepass.jl:46 =#
            local ex
            #= /home/jcaillau/.julia/packages/CTBase/fDnnG/src/onepass.jl:47 =#
            try
                #= /home/jcaillau/.julia/packages/CTBase/fDnnG/src/onepass.jl:48 =#
                state!(ocp, 2, :x, $(QuoteNode(["q", "v"])))
            catch ex
                #= /home/jcaillau/.julia/packages/CTBase/fDnnG/src/onepass.jl:50 =#
                println("Line ", 3, ": ", "x = ((q, v) ∈ R ^ 2, state)")
                #= /home/jcaillau/.julia/packages/CTBase/fDnnG/src/onepass.jl:51 =#
                throw(ex)
            end
        end
        #= REPL[5]:6 =#
        begin
            #= /home/jcaillau/.julia/packages/CTBase/fDnnG/src/onepass.jl:46 =#
            local ex
            #= /home/jcaillau/.julia/packages/CTBase/fDnnG/src/onepass.jl:47 =#
            try
                #= /home/jcaillau/.julia/packages/CTBase/fDnnG/src/onepass.jl:48 =#
                control!(ocp, 1, :u)
            catch ex
                #= /home/jcaillau/.julia/packages/CTBase/fDnnG/src/onepass.jl:50 =#
                println("Line ", 4, ": ", "(u ∈ R, control)")
                #= /home/jcaillau/.julia/packages/CTBase/fDnnG/src/onepass.jl:51 =#
                throw(ex)
            end
        end
        #= REPL[5]:8 =#
        begin
            #= /home/jcaillau/.julia/packages/CTBase/fDnnG/src/onepass.jl:46 =#
            local ex
            #= /home/jcaillau/.julia/packages/CTBase/fDnnG/src/onepass.jl:47 =#
            try
                #= /home/jcaillau/.julia/packages/CTBase/fDnnG/src/onepass.jl:48 =#
                constraint!(ocp, :variable; rg = nothing, lb = 0, ub = nothing, label = Symbol("##261"))
            catch ex
                #= /home/jcaillau/.julia/packages/CTBase/fDnnG/src/onepass.jl:50 =#
                println("Line ", 5, ": ", "tf ≥ 0")
                #= /home/jcaillau/.julia/packages/CTBase/fDnnG/src/onepass.jl:51 =#
                throw(ex)
            end
        end
        #= REPL[5]:9 =#
        begin
            #= /home/jcaillau/.julia/packages/CTBase/fDnnG/src/onepass.jl:46 =#
            local ex
            #= /home/jcaillau/.julia/packages/CTBase/fDnnG/src/onepass.jl:47 =#
            try
                #= /home/jcaillau/.julia/packages/CTBase/fDnnG/src/onepass.jl:48 =#
                constraint!(ocp, :control; rg = nothing, lb = -1, ub = 1, label = Symbol("##262"))
            catch ex
                #= /home/jcaillau/.julia/packages/CTBase/fDnnG/src/onepass.jl:50 =#
                println("Line ", 6, ": ", "-1 ≤ u(t) ≤ 1")
                #= /home/jcaillau/.julia/packages/CTBase/fDnnG/src/onepass.jl:51 =#
                throw(ex)
            end
        end
        #= REPL[5]:11 =#
        begin
            #= /home/jcaillau/.julia/packages/CTBase/fDnnG/src/onepass.jl:46 =#
            local ex
            #= /home/jcaillau/.julia/packages/CTBase/fDnnG/src/onepass.jl:47 =#
            try
                #= /home/jcaillau/.julia/packages/CTBase/fDnnG/src/onepass.jl:48 =#
                constraint!(ocp, :initial; rg = 1, lb = 1, ub = 1, label = Symbol("##263"))
            catch ex
                #= /home/jcaillau/.julia/packages/CTBase/fDnnG/src/onepass.jl:50 =#
                println("Line ", 7, ": ", "q(0) == 1")
                #= /home/jcaillau/.julia/packages/CTBase/fDnnG/src/onepass.jl:51 =#
                throw(ex)
            end
        end
        #= REPL[5]:12 =#
        begin
            #= /home/jcaillau/.julia/packages/CTBase/fDnnG/src/onepass.jl:46 =#
            local ex
            #= /home/jcaillau/.julia/packages/CTBase/fDnnG/src/onepass.jl:47 =#
            try
                #= /home/jcaillau/.julia/packages/CTBase/fDnnG/src/onepass.jl:48 =#
                constraint!(ocp, :initial; rg = 2, lb = 2, ub = 2, label = Symbol("##264"))
            catch ex
                #= /home/jcaillau/.julia/packages/CTBase/fDnnG/src/onepass.jl:50 =#
                println("Line ", 8, ": ", "v(0) == 2")
                #= /home/jcaillau/.julia/packages/CTBase/fDnnG/src/onepass.jl:51 =#
                throw(ex)
            end
        end
        #= REPL[5]:13 =#
        begin
            #= /home/jcaillau/.julia/packages/CTBase/fDnnG/src/onepass.jl:46 =#
            local ex
            #= /home/jcaillau/.julia/packages/CTBase/fDnnG/src/onepass.jl:47 =#
            try
                #= /home/jcaillau/.julia/packages/CTBase/fDnnG/src/onepass.jl:48 =#
                constraint!(ocp, :final; rg = 1, lb = 0, ub = 0, label = Symbol("##265"))
            catch ex
                #= /home/jcaillau/.julia/packages/CTBase/fDnnG/src/onepass.jl:50 =#
                println("Line ", 9, ": ", "q(tf) == 0")
                #= /home/jcaillau/.julia/packages/CTBase/fDnnG/src/onepass.jl:51 =#
                throw(ex)
            end
        end
        #= REPL[5]:14 =#
        begin
            #= /home/jcaillau/.julia/packages/CTBase/fDnnG/src/onepass.jl:46 =#
            local ex
            #= /home/jcaillau/.julia/packages/CTBase/fDnnG/src/onepass.jl:47 =#
            try
                #= /home/jcaillau/.julia/packages/CTBase/fDnnG/src/onepass.jl:48 =#
                constraint!(ocp, :final; rg = 2, lb = 0, ub = 0, label = Symbol("##266"))
            catch ex
                #= /home/jcaillau/.julia/packages/CTBase/fDnnG/src/onepass.jl:50 =#
                println("Line ", 10, ": ", "v(tf) == 0")
                #= /home/jcaillau/.julia/packages/CTBase/fDnnG/src/onepass.jl:51 =#
                throw(ex)
            end
        end
        #= REPL[5]:16 =#
        begin
            #= /home/jcaillau/.julia/packages/CTBase/fDnnG/src/onepass.jl:46 =#
            local ex
            #= /home/jcaillau/.julia/packages/CTBase/fDnnG/src/onepass.jl:47 =#
            try
                #= /home/jcaillau/.julia/packages/CTBase/fDnnG/src/onepass.jl:48 =#
                constraint!(ocp, :state; rg = 1, lb = 0, ub = 5, label = :eq1)
            catch ex
                #= /home/jcaillau/.julia/packages/CTBase/fDnnG/src/onepass.jl:50 =#
                println("Line ", 11, ": ", "(0 ≤ q(t) ≤ 5, 1)")
                #= /home/jcaillau/.julia/packages/CTBase/fDnnG/src/onepass.jl:51 =#
                throw(ex)
            end
        end
        #= REPL[5]:17 =#
        begin
            #= /home/jcaillau/.julia/packages/CTBase/fDnnG/src/onepass.jl:46 =#
            local ex
            #= /home/jcaillau/.julia/packages/CTBase/fDnnG/src/onepass.jl:47 =#
            try
                #= /home/jcaillau/.julia/packages/CTBase/fDnnG/src/onepass.jl:48 =#
                constraint!(ocp, :state; rg = 2, lb = -2, ub = 3, label = :eq2)
            catch ex
                #= /home/jcaillau/.julia/packages/CTBase/fDnnG/src/onepass.jl:50 =#
                println("Line ", 12, ": ", "(-2 ≤ v(t) ≤ 3, 2)")
                #= /home/jcaillau/.julia/packages/CTBase/fDnnG/src/onepass.jl:51 =#
                throw(ex)
            end
        end
        #= REPL[5]:19 =#
        begin
            #= /home/jcaillau/.julia/packages/CTBase/fDnnG/src/onepass.jl:46 =#
            local ex
            #= /home/jcaillau/.julia/packages/CTBase/fDnnG/src/onepass.jl:47 =#
            try
                #= /home/jcaillau/.julia/packages/CTBase/fDnnG/src/onepass.jl:48 =#
                begin
                    #= /home/jcaillau/.julia/packages/CTBase/fDnnG/src/onepass.jl:354 =#
                    function var"##269"(var"##267", var"##268", tf)
                        #= /home/jcaillau/.julia/packages/CTBase/fDnnG/src/onepass.jl:354 =#
                        #= /home/jcaillau/.julia/packages/CTBase/fDnnG/src/onepass.jl:355 =#
                        [var"##267"[2], var"##268"]
                    end
                    #= /home/jcaillau/.julia/packages/CTBase/fDnnG/src/onepass.jl:357 =#
                    dynamics!(ocp, var"##269")
                end
            catch ex
                #= /home/jcaillau/.julia/packages/CTBase/fDnnG/src/onepass.jl:50 =#
                println("Line ", 13, ": ", "ẋ(t) == [v(t), u(t)]")
                #= /home/jcaillau/.julia/packages/CTBase/fDnnG/src/onepass.jl:51 =#
                throw(ex)
            end
        end
        #= REPL[5]:21 =#
        begin
            #= /home/jcaillau/.julia/packages/CTBase/fDnnG/src/onepass.jl:46 =#
            local ex
            #= /home/jcaillau/.julia/packages/CTBase/fDnnG/src/onepass.jl:47 =#
            try
                #= /home/jcaillau/.julia/packages/CTBase/fDnnG/src/onepass.jl:48 =#
                begin
                    #= /home/jcaillau/.julia/packages/CTBase/fDnnG/src/onepass.jl:395 =#
                    function var"##270"(var"##271", var"##272", tf)
                        #= /home/jcaillau/.julia/packages/CTBase/fDnnG/src/onepass.jl:395 =#
                        #= /home/jcaillau/.julia/packages/CTBase/fDnnG/src/onepass.jl:396 =#
                        tf
                    end
                    #= /home/jcaillau/.julia/packages/CTBase/fDnnG/src/onepass.jl:398 =#
                    objective!(ocp, :mayer, var"##270", :min)
                end
            catch ex
                #= /home/jcaillau/.julia/packages/CTBase/fDnnG/src/onepass.jl:50 =#
                println("Line ", 14, ": ", "tf → min")
                #= /home/jcaillau/.julia/packages/CTBase/fDnnG/src/onepass.jl:51 =#
                throw(ex)
            end
        end
    end
    ocp.model_expression = $(QuoteNode(quote
    #= REPL[5]:3 =#
    (tf  R, variable)
    #= REPL[5]:4 =#
    (t  [0, tf], time)
    #= REPL[5]:5 =#
    x = ((q, v)  R², state)
    #= REPL[5]:6 =#
    (u  R, control)
    #= REPL[5]:8 =#
    tf  0
    #= REPL[5]:9 =#
    -1  u(t)  1
    #= REPL[5]:11 =#
    q(0) == 1
    #= REPL[5]:12 =#
    v(0) == 2
    #= REPL[5]:13 =#
    q(tf) == 0
    #= REPL[5]:14 =#
    v(tf) == 0
    #= REPL[5]:16 =#
    (0  q(t)  5, 1)
    #= REPL[5]:17 =#
    (-2  v(t)  3, 2)
    #= REPL[5]:19 =#
    (t) == [v(t), u(t)]
    #= REPL[5]:21 =#
    tf  min
end))
    ocp
end

Many thanks!

The main reason is that I feel that being able to use both syntaxes gives a better understanding of how the package is working.

Clearly there is something I am not understanding at the moment. Based on the basic example and the API I tried to rewrite the time minimization but I got an error indicatiing that I haven't defined correctly tf (abstract syntax works as expected instead).

Another reaon is that I am used to write notebooks with nteract where latex rendering is somewhat cumbersome (no tab completion). Probably I should move to Pluto but I have some inertia...

Thanks again for the swift reply and the very nice work!

@ocots
Copy link
Member Author

ocots commented Aug 12, 2024

It is now in the stable doc:

https://control-toolbox.org/OptimalControl.jl

@paolo-mgi
Copy link

paolo-mgi commented Aug 12, 2024

Excellent, Thanks! The @macroexpand tip is indeed very useful!

Now I understand. What I was missing was

dynamics!(ocp, (x, u, tf) -> [ x[2], u])

my wrong guess was instead:

dynamics!(ocp, (x, u, tf) -> [ x[2], u ,1])

@ocots
Copy link
Member Author

ocots commented Aug 12, 2024

We may need to give the mathematical syntax. Here it misses the case with a variable: https://control-toolbox.org/OptimalControl.jl/stable/tutorial-abstract.html#dynamics

@jbcaillau
Copy link
Member

@ocots well the abstract syntax does not depend on whether there is a variable or not, but I am adding a comment in the doc to complete

IMG_3430

with sth like

$$ \dot{x} = f(t, x(t), u(t), v). $$

We may need to give the mathematical syntax. Here it misses the case with a variable: https://control-toolbox.org/OptimalControl.jl/stable/tutorial-abstract.html#dynamics

@paolo-mgi
Copy link

By the way how to quote the package in a paper?

@jbcaillau
Copy link
Member

By the way how to quote the package in a paper?

good point. Zenodo ref. on its way, will tell you asap in this issue (reopened).
#175

@jbcaillau jbcaillau reopened this Aug 12, 2024
@ocots
Copy link
Member Author

ocots commented Aug 28, 2024

Hi @paolo-mgi @jbcaillau!

  • Functional syntax here.
  • Citing us here. We have a DOI from Zenodo now.

@paolo-mgi
Copy link

paolo-mgi commented Aug 28, 2024 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
documentation Improvements or additions to documentation
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants