Skip to content

ExplicitController

Matthias K. Hoffmann edited this page Jul 28, 2021 · 2 revisions

ExplicitController

controller = ExplicitController( numScenarios )

This controller will prepare the optimization problem, i.e. the expressions of the cost functions as well as the constraints, at each time step. This is done by evaluating the cost functions' getConstraints and buildExpression methods at each time step with the parameter values instead of the symbolic parameters, and by (re)building all box, delta and manual constraints for the current time step. This way, the only variables remaining the problem are those for input $u$.

This prepared problem is then solved using YALMIP's optimize(Constraints,Objective,options) function. The advantage of this controller is, that it scales very well with the number of parameters and decision variables, and thus in the number of scenarios. Furthermore, it is much more transparent for debugging, as it allows to track actual parameter values throughout the model preparation.

Of course, this scalability and transparency comes at the price of this controller being comparatively slow for small models. It is recommended to use the ExplicitController while implementing new models and cost functions, and to then try using the SymbolicController, as both can be used interchangeably and the SymbolicController can increase simulation speed dramatically for smaller models.

Configuration#

By setting the config value config.warmstart to true, warmstart will be applied. This means that the initial guesses for the current iterations input are set to the predicted input of the previous iteration. This is useful for non-linear optimization problems to get more consistent inputs. For further information, refer to YALMIP's warmstarting entry.

Free constraints using addConstraint

When using the ExplicitController, it is recommended that free constraint expression using addConstraint are wrapped into a function, instead of adding a YALMIP constraint expression directly. For clarification:

Adding a constraint expression directly:

model = createModel( .. );
param = controller.addParam( 'param', .. );
...
for s=1:numScenarios
    controller.addConstraint( 0 <= model.x{s} <= param{s} )
end

Instead, wrapping it in a function:

model = createModel( .. );
param = controller.addParam( 'param', .. );
...

controller.addConstraint( @(model, parameters, slacks, s) ( 0 <= model.x{s} <= params.param{s} ) )

The first variant should be avoided, because these constraints will contain the parametric variables for the parameters and the model, which have to be replaced using YALMIP replace each time getInput of the controller is called (i.e. at each time step). This is very, very, very slow! Instead wrapping the constraint into a function allows for directly re-creating these free constraint at each time step, which is many times faster.

Note that it does not matter which variant is used with the SymbolicController, as in both cases the free constraints will be created fully parametrically before simulation starts.