# Infinite Domains

A guide for infinite domains in `InfiniteOpt`

. See the respective technical manual for more details.

Previous versions of `InfiniteOpt`

referred to infinite domains as infinite sets. Hence, all the methods and datatypes have been updated accordingly.

## Basic Usage

Interval domains are what characterize the behavior of infinite parameters in `InfiniteOpt`

, since they comprise the domains of infinite parameters. However, most users will not need to work directly with infinite domains and can instead focus on the use of infinite parameters as defined via `@infinite_parameter`

and as discussed on the Infinite Parameters page.

However, for convenience below we summarize the infinite domains associated with `InfiniteOpt`

:

Domain Type | Domain | Type |
---|---|---|

`IntervalDomain` | $[lb, ub]$ | `InfiniteScalarDomain` |

`UniDistributionDomain` | $\sim \mathcal{D} \subseteq \mathbb{R}$ | `InfiniteScalarDomain` |

`MultiDistributionDomain` | $\sim \mathcal{D} \subseteq \mathbb{R}^n$ | `InfiniteArrayDomain` |

`CollectionDomain` | Combination of Univariate Domains | `InfiniteArrayDomain` |

## Infinite Domain Classes

The domain of a given infinite parameter(s) is described by an infinite domain (domain) inherited from `AbstractInfiniteDomain`

. `InfiniteOpt`

natively supports two domain sub-groups, namely `InfiniteScalarDomain`

s and `InfiniteArrayDomain`

s. These correspond to a single independent infinite parameter and a dependent multi-dimensional group of infinite parameters, respectively. We describe each group's natively supported domains below.

### Univariate Domains

Univariate infinite domains (i.e., `InfiniteScalarDomain`

s) are one-dimensional domains ($\subseteq \mathbb{R}$) that describe the behavior of one single independent infinite parameter (i.e., infinite parameters made using `independent = true`

). The two natively supported concrete types are `IntervalDomain`

s and `UniDistributionDomain`

s.

`IntervalDomain`

s describe a continuous interval from some lower bound up to some upper bound. Where the range is inclusive of the bounds. Such domains often arise for parameters that pertain to time and/or spatial position. For example, to define a position interval $[-2, 2]$ we would use:

```
julia> domain = IntervalDomain(-2, 2)
[-2, 2]
```

Note that (semi-)infinite bounds are acceptable, as shown in the following example:

```
julia> infinite_domain = IntervalDomain(-Inf, Inf)
[-Inf, Inf]
```

`UniDistributionDomain`

s pertain to the co-domain of a univariate distribution. In other words, these correspond to the underlying distributions that characterize uncertain scalar parameters. These domains are compatible with any univariate distribution native to `Distributions.jl`

. For example, let's make a `UniDistributionDomain`

that depends on a Beta distribution:

```
julia> using Distributions;
julia> domain = UniDistributionDomain(Beta(2,2))
Beta{Float64}(α=2.0, β=2.0)
```

User-defined distributions are also permissible so long as they are created in accordance with `Distributions.jl`

.

### Multivariate Domains

Multivariate infinite domains (i.e., [`InfiniteArrayDomain`

])(@ref)s are multi-dimensional domains that define the behavior of a group of dependent infinite parameters (i.e., an array of infinite parameters where `independent = false`

). This is a unique feature to `InfiniteOpt`

that enables a much richer set of possibilities for modeling infinite domain. Natively two domain types are supported: `MultiDistributionDomain`

s and `CollectionDomain`

s.

`MultiDistributionDomain`

s correspond to the co-domain of a multi-variate (or matrix-variate) distribution which characterizes the behavior of multi-dimensional uncertain parameters. Again, these correspond to any appropriate distribution defined in `Distributions.jl`

. For example, we can make a `MultiDistributionDomain`

that depends on a 2D normal distribution as follows:

```
julia> using Distributions;
julia> dist = MvNormal([0., 0.], [1. 0.; 0. 2.]);
julia> domain = MultiDistributionDomain(dist)
FullNormal(
dim: 2
μ: [0.0, 0.0]
Σ: [1.0 0.0; 0.0 2.0]
)
```

The dimensions (shape) of a chosen distribution used in an `MultiDistriubtionDomain`

must match those of the corresponding infinite parameter array.

Finally, `CollectionDomain`

s are a dependent collection of `InfiniteScalarDomain`

s that correspond to a group of infinite parameters that are treated dependently. This can be useful when the user wishes to have complete control over how the supports are generated for a group independent parameters where the default combinatorial approach in not wanted. For example, let's make a set of `IntervalDomain`

s:

```
julia> domain = CollectionDomain([IntervalDomain(-2, 2), IntervalDomain(-1, 4)])
CollectionDomain with 2 domains:
[-2, 2]
[-1, 4]
```

Now we could use this domain in define a two-dimensional infinite parameter of which we can have the freedom to define a non-combinatorial support grid.

## Bound Query/Modification Methods for Infinite Domains

Once an infinite domain is created, one can query the lower bound and upper bound of the domain similar to how one queries the bounds of a `JuMP`

variable. Thus, the functions `JuMP.has_lower_bound`

, `JuMP.has_upper_bound`

, `JuMP.lower_bound`

, `JuMP.upper_bound`

are all applicable to infinite domains mentioned above. For example, for an `IntervalDomain`

`[-2, 2]`

we can query the bound information as follows:

```
julia> domain = IntervalDomain(-2, 2);
julia> has_lower_bound(domain)
true
julia> has_upper_bound(domain)
true
julia> lower_bound(domain)
-2.0
julia> upper_bound(domain)
2.0
```

In addition, we can also apply `JuMP.set_lower_bound`

and `JuMP.set_upper_bound`

to `IntervalDomain`

s to generate a new domain with updated bounds. Note that this will not modify the original domain. For example, we can change the bounds of the set `[-2, 2]`

as follows:

```
julia> set_lower_bound(domain, -1)
[-1, 2]
julia> set_upper_bound(domain, 1)
[-2, 1]
```

## Support Generation for Infinite Domains

`InfiniteOpt`

provides a systematic interface to generate support points for infinite domains. This is crucial as support generation decides how each infinite-dimensional parameter, which is subject to certain infinite domain, is discretized later in the transcription stage. The interface will allow users to automatically generate support points using our default methods. Later we will also show that users can also input support points manually for an infinite parameter. Please note that these methods are called by the `@infinite_parameter`

macro when the `num_supports`

keyword is used. Thus, users typically will not need to use this interface directly.

In `InfiniteOpt`

supports can be generated via `generate_supports`

function. For example, let's generate 5 equidistant support points for the `IntervalDomain`

[-2, 2]:

```
julia> supps, label = generate_supports(domain, num_supports = 5)
([-2.0, -1.0, 0.0, 1.0, 2.0], UniformGrid)
```

Note that the number of supports generated is specified via `num_supports`

keyword argument, which will take a default value of 10 if not specified. The function `generate_supports`

returns a vector of the supports generated, and a label that denotes the underlying method. In this case the label returned is `UniformGrid`

, which is the default support generation method for `IntervalDomain`

s. Another support generation method implemented for `IntervalDomain`

s is `MCSample`

, which is to sample from a uniform distribution over the interval. To use this method, users need to specify a second positional argument, as shown in the following example:

```
julia> generate_supports(domain, MCSample, num_supports = 5, sig_digits = 5)
([1.2946, 1.6414, -1.3417, -1.2907, -0.88448], MCSample)
```

In this case, the returned label is `MCSample`

, instead of `UniformGrid`

.

`generate_supports`

can also be applied to `DistributionDomains`

. The default (and currently only) method implemented for `DistributionDomains`

is `WeightedSample`

, which generates Monte Carlo samples that are weighted based on the underlying probability density function of the distribution. For example, a domain of support points for a 2D normal distribution can be generated as follows:

```
julia> dist = MvNormal([0., 0.], [1. 0.;0. 2.]);
julia> domain = MultiDistributionDomain(dist);
julia> supps, label = generate_supports(domain, num_supports = 3)
([0.679107426036 -0.353007400301 0.586617074633; 1.17155358277 -0.190712174623 0.420496392851], WeightedSample)
```

For those who are interested in coding up their own support generation functions, `generate_supports`

is an interface that calls the proper `generate_support_values`

function based on the type of domain and value of method. Therefore, to use custom support generation methods, users can implement extensions for `generate_support_values`

with a different method label from the existing methods. See Extensions for full details.

## User Defined Domains

Furthermore, custom infinite domains that inherit `AbstractInfiniteDomain`

can also be defined. See Extensions for more information.