Finite Parameters

A guide for the definition and use of finite parameters in InfiniteOpt. See the respective technical manual for more details.

Overview

Often a mathematical model needs to be optimized several times in accordance with a set of fixed parameter values. In such cases, it is typically preferable to modify these values in place without having to redefine the entire model. This ability is provided in InfiniteOpt via @finite_parameter which permits users to define finite parameters whose values can later be modified as needed. Furthermore, at the optimization step these parameters are replaced with their numeric values. Thus, not adding unnecessary decision variables as is typically done in JuMP models using JuMP.fix on placeholder variables.

Warning

In some cases, using @finite_parameter can unexpectedly make the underlying transformation backend contain nonlinear constraints/objectives. This occurs when a quadratic expression is mutliplied by a finite parameter (making a GenericNonlinearExpr):

julia> model = InfiniteModel(); @variable(model, z); @finite_parameter(model, p == 2);

julia> @objective(model, Min,  p * z^2) # becomes a nonlinear objective 
p * (z²)

In these cases, a nonlinear solver like Ipopt should be used or the finite parameter syntax should be avoided if a quadratic solver like Gurobi is needed.

Basic Usage

Once an InfiniteModel model has been defined we can add a finite parameter via @finite_parameter. For example, let's define a maximum cost parameter called max_cost with an initial value of 42:

julia> @finite_parameter(model, max_cost == 42)
max_cost

Notice that a Julia variable called max_cost is returned that contains a GeneralVariableRef that points to the finite parameter we have just created. An array of parameters can also be defined following standard JuMP macro syntax:

julia> values = [2, 3.2, 1];

julia> @finite_parameter(model, params[i = 1:3] == values[i])
3-element Vector{GeneralVariableRef}:
 params[1]
 params[2]
 params[3]

The @finite_parameter macro emulates all typical JuMP functionality and can define anonymous parameters, use JuMP containers and more. We refer to its documentation below to learn more. Once a finite parameter is defined the corresponding GeneralVariableRef can be used in expressions, objectives, measures, and constraints just like infinite parameters.

The value of a finite parameter can be checked using parameter_value and can modified using set_value. For example, let's update the value of max_cost to be now be 10.2:

julia> parameter_value(max_cost)
42.0

julia> set_value(max_cost, 10.2)

julia> parameter_value(max_cost)
10.2

Advanced Details

The ability to implement finite parameters stems from its ability to support mixed variable types using by using the GeneralVariableRef buffer. As such, finite parameters will be treated as variables until the model is transcribed. For example, this means that the expression max_cost * x will be treated as a quadratic expression when it is expressed in its InfiniteOpt form, however it is converted into the appropriate affine expression when transcribed.

Note

In previous versions finite parameters were just special cases of infinite parameters. However, they now have their own distinct underlying data structure.

Warning

InfiniteOpt's implementation of finite parameters should not be a reason to use InfiniteOpt to model non-infinite-dimensional problems, since the added overhead will make it slower than just iteratively building JuMP models. For this behavior, we recommend looking into using ParametricOptInterface.