Objectives
A guide specifying and modifying objective functions in InfiniteOpt
. See the respective technical manual for more details.
Overview
Naturally, objective functions serve as a key aspect of optimization problems in general and this is certainly the case with infinite dimensional ones. In InfiniteOpt
objectives are defined in much the same way they are in JuMP
. One key idea to keep in mind is that the objective must evaluate to a finite expression. Note this means that objectives can only explicitly contain finite variables and point variables. Infinite expressions must be evaluated in a measure to be included (e.g., evaluate the expectation of a random variable).
Basic Usage
Principally, the objective function is specified via @objective
as is done in JuMP
. For example, let's define the stochastic objective to minimize $0.5 x_1 + 0.5 x_2 + \mathbb{E}_\xi [y^2 - y]$:
julia> @infinite_parameter(model, ξ ~ Normal())
ξ
julia> @variable(model, y, Infinite(ξ))
y(ξ)
julia> @variable(model, x[1:2])
2-element Vector{GeneralVariableRef}:
x[1]
x[2]
julia> @objective(model, Min, 0.5x[1] + 0.5x[2] + 𝔼(y^2 - y, ξ))
0.5 x[1] + 0.5 x[2] + 𝔼{ξ}[y(ξ)² - y(ξ)]
Thus, we have defined an objective using InfiniteOpt
's straightforward syntax. Note that the second argument indicates the objective sense which can be expressed Min
for minimization problems and Max
for maximization problems. The objective function (expression) must be finite containing only finite variables, point variables, and/or measures. Also, any included measures must fully integrate over all the infinite parameters contained in its input function. For example, if we define had an infinite variable z(ξ, t)
then the measure 𝔼(z, ξ)
could not be included since the resulting expression would still be infinite with respect to t
. However, adding a measure for t
would result in a valid object to add to an objective: ∫(𝔼(z, ξ), t)
.
Nonlinear objectives are defined simply by using @objective
and not using JuMP.@NLobjective
. See Nonlinear Expressions for more information.
Now we can add objectives to our infinite models. For more detailed information, please review the information below.
Queries
This section will highlight the available methods for extracting objective information. These are all derived from extensions to JuMP
functions and thus follow syntax.
Principally, these methods correspond to objective_sense
, objective_function
, and objective_function_type
which return the objective sense (a subtype of MOI.OptimizationSense
), the objective function (expression), and the objective function type, respectively. These methods are demonstrated in accordance with the example presented above in the Basic Usage section:
julia> objective_sense(model)
MIN_SENSE::OptimizationSense = 0
julia> objective_function(model)
0.5 x[1] + 0.5 x[2] + 𝔼{ξ}[y(ξ)² - y(ξ)]
julia> objective_function_type(model)
GenericAffExpr{Float64, GeneralVariableRef}
The objective sense can be one of three possibilities: MIN_SENSE
, MAX_SENSE
, or FEASIBILITY_SENSE
. The later sense applies to models that contain no objective function.
Modification
This section will review the methods that can be used to modify the objective. First, we'll consider the useful set_objective_coefficient
method, and then we'll explain the methods that enable @objective
.
The coefficient of a particular variable in an objective can be readily updated via set_objective_coefficient
. This is useful repeatedly optimizing an infinite model with varied objective coefficients (e.g., varied tradeoff parameters). For example, let's consider updating the coefficient of x[1]
in the previous example from 0.5 to 0.25:
julia> set_objective_coefficient(model, x[1], 0.25)
julia> objective_function(model)
0.25 x[1] + 0.5 x[2] + 𝔼{ξ}[y(ξ)² - y(ξ)]
Now let's consider the modification methods that enable the @objective
macro. The objective function is specified via set_objective_function
which simply updates the expression stored in the objective. For example, let's update out objective to simply be $0.5x_1 + 0.5x_2$:
julia> set_objective_function(model, 0.5x[1] + 0.5x[2])
julia> objective_function(model)
0.5 x[1] + 0.5 x[2]
The objective sense is updated via set_objective_sense
which can specify the sense as one of the MOI.OptimizationSense
subtypes. For example, let's change the current objective to be maximization problem:
julia> set_objective_sense(model, MOI.MAX_SENSE)
julia> objective_sense(model)
MAX_SENSE::OptimizationSense = 1
The above 2 methods are both called via set_objective
. This is the function that enables @objective
behind the scenes. Thus, the previous 2 examples could have been implemented equivalently in the following ways:
julia> set_objective(model, MOI.MAX_SENSE, 0.5x[1] + 0.5x[2])
julia> @objective(model, Max, 0.5x[1] + 0.5x[2])
0.5 x[1] + 0.5 x[2]
Notice that @objective
offers a more intuitive syntax and is also more efficient at parsing expressions.
When possible, the @objective
since it is more stable and efficient than the set_objective_[aspect]
methods due to its enhanced methodology for parsing expressions.