3. Solving optimization problems

The first step when solving an optimization problem is to formulate a model and an optimization specification and then compile the model as described in the following sections in this chapter. There are four different optimization algorithms available in JModelica.org, which are suitable for different classes of optimization problems.

To illustrate how to solve optimization problems the Van der Pol problem presented above is used. First, the model is compiled and loaded:

model_name = compile_jmu("VDP_Opt","VDP_Opt.mop")
model = JMUModel(model_name)

In this case, a JMU is compiled, corresponding compilation functions are available for the other algorithms. All operations that can be performed on the model are available as methods of the model object and can be accessed by tab completion. Invoking an optimization algorithm is done by calling the method JMUModel.optimize, which performs the following tasks:

The interactive help for the optimize method is displayed by the command:

>>> help(model.optimize)
    Solve an optimization problem.
        algorithm --
            The algorithm which will be used for the optimization is 
            specified by passing the algorithm class name as string or 
            class object in this argument. 'algorithm' can be any 
            class which implements the abstract class AlgorithmBase 
            (found in algorithm_drivers.py). In this way it is 
            possible to write custom algorithms and to use them with this 
            The following algorithms are available:
            - 'CollocationLagrangePolynomialsAlg'. This algorithm is based on
              direct collocation on finite elements and the algorithm IPOPT
              is used to obtain a numerical solution to the problem.
            Default: 'CollocationLagrangePolynomialsAlg'
        options -- 
            The options that should be used in the algorithm. The options
            documentation can be retrieved from an options object:
                >>> myModel = JMUModel(...)
                >>> opts = myModel.optimize_options()
                >>> opts?
            Valid values are: 
            - A dict that overrides some or all of the default values
              provided by CollocationLagrangePolynomialsAlgOptions. An empty
              dict will thus give all options with default values.
            - A CollocationLagrangePolynomialsAlgOptions object.
            Default: Empty dict
        A result object, subclass of algorithm_drivers.ResultBase.

Again, note that the parameters differs for different model classes. The optimize method can be invoked without any arguments, in which case the default optimization algorithm, with default options, is invoked:

res = vdp.optimize()

In the remainder of this chapter the available algorithms are described in detail. Options for an algorithm can be set using the options argument to the optimize method. It is convenient to first obtain an options object in order to access the documentation and default option values. This is done by invoking the method optimize_options:

>>> help(m.optimize_options)
    Returns an instance of the optimize options class containing options 
    default values. If called without argument then the options class for 
    the default optimization algorithm will be returned.
        algorithm --
            The algorithm for which the options class should be returned. 
            Possible values are: 'CollocationLagrangePolynomialsAlg'.
            Default: 'CollocationLagrangePolynomialsAlg'
        Options class for the algorithm specified with default values.

The option object is essentially a Python dictionary and options are set simply by using standard dictionary syntax:

opts = vdp.optimize_options()
opts['n_e'] = 5

The optimization algorithm may then be invoked again with the new options:

res = vdp.optimize(options=opts)

Available options for each algorithm are documented in their respective sections in this Chapter.

The optimize method returns a result object containing the optimization result and some meta information about the solution. The most common operation is to retrieve variable trajectories from the result object:

time = res['time']
x1 = res['x1']

Variable data is returned as NumPy arrays. The result object also contains references to the model that was optimized, the name of the result file that was written to disk, a solver object representing the optimization algorithm and an options object that was used when solving the optimization problem.