OptimalControlProblem

class moba_muscod.OptimalControlProblem

High-level user-interface class for Optimal Control Problems.

Object-oriented representation of a mathematical Optimal Control Problem. All components are defined by appropriate set functions. System dynamics and variable names are defined by a given FMU. Additional cost functions and constraints needs do be given as strings. Several default settings can be changed.

addConstraint(constr, shootingNode, stageIndex=0)

Add a inequality or equality constraint to the specified stage of the optimal control problem.

Parameters:
  • constr (str) – Symbolic expression for constraint using =,>,<
  • shootingNode (str) – Describes at which shooting node of the stage the constraint is valid - “s” : at the start point of the stage - “i” : at the interior multiple shooting nodes of the stage - “e” : at the end point of the stage - “*” : at all shooting nodes of the stage
  • stageIndex (int, optional) – Index of selected stage. Only relevant for multi-stage problems.
addCoupledConstraint(constr)

Add a constraint, that couples variables at different time points.

Parameters:constr (str) – Symbolic expression for constraint using =,>,< and [stageIndex;shootingNode], where stageIndex is of type int and shootingNode is one of s, i, e, *

Examples

State x0 at the beginning of stage 0 must be equal to state x0 at then end of stage 0:

>>> ocp = OptimalControlProblem()
>>> ocp.loadFMU('FirstOrder.fmu')
<BLANKLINE>
...
>>> ocp.addCoupledConstraint('x0[0;s] = x0[0;e]')
addCyclicSteadyStateConstraints(states=None)

Add cyclic steady state constraints to the optimal control problem.

For given states equality constraints are added. Their values at start and end time must be equal. Which corresponds to a cyclic steady state of an periodic process.

Parameters:states (array-like, optional) – Index of states, that should be included. All states are included if nothing is given (default).

Examples

Add cyclic steady state constraints for x0:

>>> ocp = OptimalControlProblem()
>>> ocp.loadFMU('FirstOrder.fmu')
<BLANKLINE>
...
>>> ocp.addCyclicSteadyStateConstraints([0])
addEnergyTerm(variable, unit='', stageIndex=0, weight=1.0)

Add a energy term to cost function.

A given model variable, describing an ernergy flow, is added as Lagrange term to the cost function. That means, its integrated value over the complete stage duration is minimized.

Parameters:
  • variable (str) – Model variable describing an energy flow. Can be alias or FMU name.
  • unit (str, optional) – Unit of variable.
  • stageIndex (int, optional) – Index of selected stage. Only relevant for multi-stage problems.
  • weight (float, optional) – Weighting factor for cost function term.
addFitDataTerm(data, variable, stageIndex=0, weight=1.0)

Add a fit data term to cost function.

Parameters:
  • data (array-like) – Reference data as array over time. Time points are defined by shooting nodes.
  • variable (str) – Dependend model variable that corresponds to reference data. Can be alias or FMU name.
  • stageIndex (int, optional) – Index of selected stage. Only relevant for multi-stage problems.
  • weight (float, optional) – Weighting factor for cost function term.

Examples

>>> ocp = OptimalControlProblem()
>>> ocp.loadFMU('FirstOrder.fmu')
<BLANKLINE>
...
>>> ocp.setTimeHorizon(5, 2.0)
>>> ocp.addFitDataTerm([0.000,1.105,1.967,2.638,3.160,3.567], 'x0')
addSetPointTerm(setPoint, variable, stageIndex=0, weight=1.0)

Add a set point term to cost function.

Parameters:
  • setPoint (float) – Value for set point
  • variable (str) – Controlled model variable. Can be alias or FMU name.
  • stageIndex (int, optional) – Index of selected stage. Only relevant for multi-stage problems.
  • weight (float, optional) – Weighting factor for cost function term.

Examples

Control first model state to a set point of 2.0:

>>> ocp = OptimalControlProblem()
>>> ocp.loadFMU('FirstOrder.fmu')
<BLANKLINE>
...
>>> ocp.addSetPointTerm(2.0, 'x0')
addStage()

Add additional stage to the Optimal Control Problem.

The configuration is copied from the first stage. This includes the FMU, the variable dimensions and names.

Examples

>>> ocp = OptimalControlProblem()
>>> ocp.loadFMU('FirstOrder.fmu')
<BLANKLINE>
...
>>> new_stage = ocp.addStage()
addTransitionStage(fcn=None)

Add transition stage to the Optimal Control Problem.

Transition stages can be used to model discontinuities of state variables. Default behaviour is to set all fixed states to their initial value and force continuity for non fixed states.

Parameters:fcn (str, optional) – C++ code for transition function.
compileCPP()

Compile MUSCOD’s cpp file.

compileTestBench(writeCPP=True)

Generate a stand alone executable to test FMU without MUSCOD.

estimateSettings(u=None, p=None, initial=True, bounds=True, scales=True)

Estimate OCP settings for differential states and inputs.

Simulates the FMU starting from its internal initial values. The inputs can be set to a given value. Initial values, lower and upper bounds and scale values for all OCP variables are estimated based on the simulation result.

Parameters:
  • u (array-like, optional) – Values for inputs. If omitted, start values will be read from the model.
  • p (array-like, optional) – Values for selected parameters. If omitted, start values will be read from the model.
  • initial (bool, optional) – True, if inital values should be estimated
  • bounds (bool, optional) – True, if upper and lower bounds should be estimated
  • scales (bool, optional) – True, if scale values should be estimated
exportResultToMatlab(filename='B')

Write optimization result to a Matlab file.

exportResultToModelica(fileName='A')

Write optimization result to a Modelica file.

A .mo file is generated, where initial states, stage lengths and control trajectories are stored as modelica package. This modelica package can be used to resimulate optimization results in a Modelica tool.

Parameters:fileName (str, optional) – Name of .mo file to export
loadFMU(path)

Load dynamic system model.

The system model describes the dynamic part of the Optimal Control Problem. It must be stored according to FMI 2.0 for model exchange. Inputs are interpreted as control variables.

Parameters:path (str) – Full path of FMU

Examples

>>> ocp = OptimalControlProblem()
>>> ocp.loadFMU('FirstOrder.fmu')
<BLANKLINE>
Found input variables:
<BLANKLINE>
u0:  u
<BLANKLINE>
Found parameters:
<BLANKLINE>
p0:  k
p1:  T
<BLANKLINE>
Found differential states:
<BLANKLINE>
x0:  x
<BLANKLINE>
Found output variables:
<BLANKLINE>
loadSettings(path='result.xlsx', stageIndex=-1, resultAsStart='none')

Load settings for time horizon, controls and differential states from excel file.

Parameters:
  • path (string) – Path from which file is loaded
  • stageIndex (int, optional) – Index of selected stage. Only relevant for multi-stage problems. Use -1 for all stages (default).
  • resultAsStart ({'none', 'all', 'controls'}, optional) – Use result of previous optimization as start values, for all variables or for controls only.
plotResult(statesIndex=None, discreteResults=False)

Plot optimization result in Python.

printSettings(onlyFirstShootingNode=True, stageIndex=0)

Print variable settings.

Parameters:
  • onlyFirstShootingNode (bool, optional) – Print settings at first shooting node or at all shooting nodes.
  • stageIndex (int, optional) – Index of selected stage. Only relevant for multi-stage problems.
resetCostFunctions()

Delete all cost function tersm.

saveSettings(path='', stageIndex=0)

Save settings for time horizon, controls and differential states to excel file.

Parameters:
  • path (string, optional) – Path to which the file is saved
  • stageIndex (int, optional) – Index of selected stage. Only relevant for multi-stage problems.
selectParameters(parameters)

Select some of the available parameters as optimization variable.

A FMU can have a lot of tunable parameters. When loading a FMU, all of them are included in the OCP. This functions selects one or several parameters and discards all others.

Parameters:parameters (list) – List of selected parameter names (str)

Examples

>>> ocp = OptimalControlProblem()
>>> ocp.loadFMU('FirstOrder.fmu')
<BLANKLINE>
...
>>> ocp.selectParameters(['T'])
Selected Parameters:
<BLANKLINE>
  alias name       ref
1    p1    T  16777217
<BLANKLINE>
<BLANKLINE>
setCostFunction(lval=None, mval=None, stageIndex=0, weight=1.0)

Set cost function of Optimal Control Problem.

The cost function can be a Lagrange term, a Mayer term or both types combined. Lagrange terms are integrated over the whole time horizon. Mayer terms are evaluated only at the end time. Cost functions are provided as C-code strings according to MUSCOD’s definitions. FMU variable names of states and controls are automatically replaced by MUSCOD’s array expressions. These strings are directly inserted into the generated C-code.

Parameters:
  • lval (str, optional) – C-code string for Lagrange cost function
  • mval (str, optional) – C-code string for Mayer cost function
  • stageIndex (int, optional) – Index of selected stage. Only relevant for multi-stage problems.
  • weight (float, optional) – Weighting factor for cost function term.

Examples

Minimize integrated squared deviation of the first state variable from a fixed set point of 1.0:

>>> ocp = OptimalControlProblem()
>>> ocp.loadFMU('FirstOrder.fmu')
<BLANKLINE>
...
>>> ocp.setCostFunction(lval = '(x0-1.0)*(x0-1.0)')

Or minimize the value of the state variable at the end of time horizon:

>>> ocp.setCostFunction(mval = 'x0')
setInitialValues(xInit=None, uInit=None, pInit=None, xFixed=None, uFixed=None, pFixed=None, stageIndex=0)

Set initial values for states, controls and parameters.

Parameters:
  • xInit (array-like, optional) – Initial values for states. Values are propagated to all shooting nodes.
  • uInit (array-like, optional) – Initial values for controls. Values are propagated to all shooting nodes.
  • pInit (array-like, optional) – Initial values for global parameters.
  • xFixed (array-like or bool, optional) – Indicates if states are fixed to its start value at the fist shooting node.
  • uFixed (array-like or bool, optional) – Indicates if controls are fixed to its start value at all shooting nodes.
  • pFixed (array-like or bool, optional) – Indicates if global parameters are fixed to its start value.
  • stageIndex (int, optional) – Index of selected stage. Only relevant for multi-stage problems.

Examples

>>> ocp = OptimalControlProblem()
>>> ocp.loadFMU('FirstOrder.fmu')
<BLANKLINE>
...
>>> ocp.setInitialValues(xInit=[-1.0], uInit=[2.0], pInit=[0.75, 2.5], pFixed=[False, True])
setLowerBounds(xBounds=None, uBounds=None, pBounds=None, stageIndex=0)

Set lower bounds for states, controls and parameters.

Parameters:
  • xBounds (array-like, optional) – Bound values for states. Values are propagated to all shooting nodes.
  • uBounds (array-like, optional) – Initial values for controls. Values are propagated to all shooting nodes.
  • pBounds (array-like, optional) – Initial values for parameters.
  • stageIndex (int, optional) – Index of selected stage. Only relevant for multi-stage problems.

Examples

>>> ocp = OptimalControlProblem()
>>> ocp.loadFMU('FirstOrder.fmu')
<BLANKLINE>
...
>>> ocp.setLowerBounds(xBounds=[-10.0], uBounds=[-10.0])
setRandomGuessValues(stageIndex=0)

Set all variables that are not fixed to random values.

Random values are generated by a uniform distribution between lower and upper bounds of the variables.

Parameters:stageIndex (int, optional) – Index of selected stage. Only relevant for multi-stage problems.
setScaleValues(xScale=None, uScale=None, pScale=None, cScale=None, stageIndex=0)

Set scale values for states, controls and parameters.

Scale values are internally used to normalize all variables. For numerical optimization algorithms proper scaling is very important.

Parameters:
  • xScale (array-like, optional) – Scale values for states. Values are propagated to all shooting nodes.
  • uScale (array-like, optional) – Scale values for controls. Values are propagated to all shooting nodes.
  • pScale (array-like, optional) – Scale values for parameters.
  • cScale (float, optional) – Scale value for cost function.
  • stageIndex (int, optional) – Index of selected stage. Only relevant for multi-stage problems.

Examples

>>> ocp = OptimalControlProblem()
>>> ocp.loadFMU('FirstOrder.fmu')
<BLANKLINE>
...
>>> ocp.setScaleValues(xScale=[1.0], uScale=[5.0])
setTimeHorizon(nmsi, hstart, hscale=None, hlbound=None, hubound=None, hFixed=True, stageIndex=0)

Set time horizon settings of Optimal Control Problem.

Parameters:
  • nmsi (int) – Number of multiple shooting intervals
  • hstart (float) – Start value for time horizon length in seconds
  • hscale (float, optional) – Scale of time horizon length in seconds. If not provided, hstart is used.
  • hlbound (float, optional) – Lower bound for time horizon length in seconds. If not provided, hstart is used.
  • hubound (float, optional) – Upper bound for time horizon length in seconds. If not provided, hstart is used.
  • hFixed (bool, optional) – Indicates if time horizon length is fixed (default) or free for optimization.
  • stageIndex (int, optional) – Index of selected stage. Only relevant for multi-stage problems.

Examples

Use a fixed time horizon of 5 seconds discretized into 20 equidistant multiple shooting intervals:

>>> ocp = OptimalControlProblem()
>>> ocp.loadFMU('FirstOrder.fmu')
<BLANKLINE>
...
>>> ocp.setTimeHorizon(20, 5.0)
setUpperBounds(xBounds=None, uBounds=None, pBounds=None, stageIndex=0)

Set upper bounds for states, controls and parameters.

Parameters:
  • xBounds (array-like, optional) – Bound values for states. Values are propagated to all shooting nodes.
  • uBounds (array-like, optional) – Initial values for controls. Values are propagated to all shooting nodes.
  • pBounds (array-like, optional) – Initial values for parameters.
  • stageIndex (int, optional) – Index of selected stage. Only relevant for multi-stage problems.

Examples

>>> ocp = OptimalControlProblem()
>>> ocp.loadFMU('FirstOrder.fmu')
<BLANKLINE>
...
>>> ocp.setUpperBounds(xBounds=[10.0], uBounds=[20.0])
setWorkingDirectory(path)

Change working directory, where all generated files are stored.

Parameters:path (str) – New path
solve(writeDAT=True, writeCPP=True, compileCPP=True, i='', verbose=True, template=None)

Start solving of optimal control problem.

writeCPP(template='template.cpp')

Write MUSCOD’s cpp file.

writeDAT()

Write MUSCOD’s dat file.