# 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.