csu-hmc / opty

A library for using direct collocation in the optimization of dynamic systems.
http://opty.readthedocs.io
Other
86 stars 20 forks source link

args and kwargs for create_objective_function #122

Open moorepants opened 4 months ago

moorepants commented 4 months ago

Current is:

def create_objective_function(
    objective, state_symbols, input_symbols, unknown_symbols,
    N, node_time_interval=1.0, integration_method="backward euler"):

What is required:

what is optional:

You need either input symbols or unknown symbols and the input symbols are any functions of time that are not state symbols, so they can actually be detected. A pure parameter id problem only needs unknown symbols, not input symbols and a pure open loop trajectory optimization only needs input_symbols.

The time interval always has to be specified and the chances that it is 1.0 is very low, so I think it should be an arg.

Technically the integration method is required so an arg may be best, but given that the default is backward euler in Problem, it is probably fine to keep it this way.

My suggestion would be to adjust the args and kwargs to make:

tjstienstra commented 4 months ago

The problem with automatic detection is that you only know the objective and some variables may be missing from there. If one unknown trajectory misses, then you by definition don't know what your free vector will look like. Similar for the unknown parameters.

The reason for interval_value to be a kwarg is that it only scales the problem.

moorepants commented 4 months ago

The problem with automatic detection is that you only know the objective and some variables may be missing from there. If one unknown trajectory misses, then you by definition don't know what your free vector will look like. Similar for the unknown parameters.

Yep, didn't think of that. I think that the later two should be kwargs still though, otherwise you have to pass tuple() when you want it to be effectively None.

tjstienstra commented 4 months ago

Another option would be to change the signature of Problem. This could also enhance user experience. This could look a bit like this:

# Assume obj and obj_grad are passed
obj = args[0] if args else kwargs.get("obj")
obj_grad args[1] if len(args)>1 else kwargs.get("obj_grad")
It "obj_expr" in kwargs:
    if isinstance(args[0], Callable) or isinstance(args[1], Callable):
         raise ValueError("The objective function should be provided either as expression ('obj_expr')or as two evaluation functions ('obj', 'obj_grad').")
    obj, obj_grad = create_objective_function(...)
else:
    args = args[2:]  # Something like this
moorepants commented 4 months ago

I'm open to that.

moorepants commented 4 months ago

But, I suspect the function may fail if people throw more random objective functions at it. We need to be clear on what it can and can't do.