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

Open contributions #286

Open
ocots opened this issue Aug 11, 2024 · 2 comments
Open

Open contributions #286

ocots opened this issue Aug 11, 2024 · 2 comments
Assignees

Comments

@ocots
Copy link
Member

ocots commented Aug 11, 2024

It could be great to encourage contributions. We need:

  • a tutorial explaining how to contribute
  • some CI to make some tests to decide acceptation

How to contribute

Let us consider you want to add a method to solve an optimal control problem. First, you need to define a method which takes an optimal control problem as input and returns a solution. More precisely, the signature should be of the form:

using CTBase: OptimalControlModel, OptimalControlSolution
 
mysolve(
    ocp::OptimalControlModel, 
    description::Symbol...;
    kwargs...
)::OptimalControlSolution

API

The types OptimalControlModel and OptimalControlSolution are mutable structs:

However, it is better not to access fields directly in the case of a change in the api. Hence, it would be better to access data of the model from the getters.

To construct an OptimalControlSolution, please use the following constructors:

where Fixed means that there are no variables in the problem and NonFixed the contrary.

Customize the signature of your solver

Actually, you can customize the keyword arguments. For the other arguments, they must be ocp::OptimalControlModel, description::Symbol.... However, for the keyword arguments, you can set you own. Imagine your solver needs an initial guess, then, you can decide to define:

using CTBase: OptimalControlModel, OptimalControlSolution
 
mysolve(
    ocp::OptimalControlModel, 
    description::Symbol...;
    init,                                          # initial guess
    kwargs...
)::OptimalControlSolution

Note that we provide a default valuer for the initial guess: CTBase.__ocp_init(). It is simply nothing. Hence, you can choose to set the default value and define:

using CTBase: OptimalControlModel, OptimalControlSolution, __ocp_init
 
mysolve(
    ocp::OptimalControlModel, 
    description::Symbol...;
    init::__ocp_init(),                      # initial guess
    kwargs...
)::OptimalControlSolution

The two required methods

The first method which is required is mysolve. The second method must be named available_methods. This method returns a list of descriptions that correspond to possibilities offered by your solver. Imagine you use ADNLPModels.jl to modelise the optimisation problem (if you transform the optimal control problem to an optimisation problem) and you use either Ipopt or MadNLP to solve the optimisation problem. In this case, you can define:

function available_methods()
    # available methods by order of preference
    algorithms = ()
    algorithms = add(algorithms, (:adnlp, :ipopt))
    algorithms = add(algorithms, (:adnlp, :madnlp))
    return algorithms
end

Note that :adnlp is not strictly necessary since there is no alternative but it permits to prepare future possibilities or to explicit a little bit more the method.

Note that the descriptions are added by order of priority. If the user makes:

mysolve(ocp, :adnlp)

then, the chosen method is (:adnlp, :ipopt). The user may not give a complete description. The following are equivalent:

mysolve(ocp)
mysolve(ocp, :adnlp)
mysolve(ocp, :adnlp, :ipopt)

To recap, you need to define:

  • mysolve
  • available_methods

Initial guess

To be completed

Add you method to OptimalControl

To be completed

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

No branches or pull requests

1 participant