---
title: "om() - ADAM-based occurrence model"
author: "Ivan Svetunkov"
date: "`r Sys.Date()`"
output: rmarkdown::html_vignette
vignette: >
  %\VignetteIndexEntry{om() - ADAM-based occurrence model}
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteEncoding{UTF-8}
bibliography: library.bib
---

```{r global_options, include=FALSE}
knitr::opts_chunk$set(fig.width=6, fig.height=4, fig.path='Figs/', fig.show='hold',
                      warning=FALSE, message=FALSE)
library(smooth)
```

The `om()` function is the ADAM-based occurrence model for intermittent demand data. It estimates the probability of demand occurrence $p_t$ using the full ADAM state-space framework, which means the underlying model for the occurrence dynamics can be an ETS model, an ARIMA model, a regression model, or a combination of all three.

The five link functions (occurrence types) supported by `om()` are identical to those in `oes()`: **fixed**, **odds-ratio**, **inverse-odds-ratio**, **direct**, and **general**. For the mathematical derivations behind each link function see the [oes vignette](oes.html). This vignette focuses on the added flexibility that `om()` inherits from ADAM.


## The data

We use the same artificial data as in the oes vignette:

```{r data}
set.seed(41)
y <- ts(c(rpois(20, 0.25), rpois(20, 0.5), rpois(20, 1),
          rpois(20, 2),    rpois(20, 3),    rpois(20, 5)))
```

The series starts sparse (low Poisson rate) and becomes increasingly dense. Any non-zero value in the input is automatically binarised to 1 by `om()`, so passing a count series is fine.


## om(): ETS occurrence model

The simplest call resembles `oes()`. We fix an ETS(M,N,N) model and use the odds-ratio link:

```{r etsManual}
omETS <- om(y, model="MNN", occurrence="odds-ratio", h=10, holdout=TRUE)
omETS
plot(omETS, 7)
```

Model selection across ETS components is supported through the same `"Z"` / `"X"` / `"Y"` wildcards used in `adam()` and `es()`. The default `model="ZXZ"` searches across all sensible error types and seasonal patterns:

```{r etsAuto}
omETSAuto <- om(y, occurrence="odds-ratio", h=10, holdout=TRUE)
omETSAuto
```

The fitted occurrence model can be passed directly to `adam()` for a full iETS model that jointly describes demand occurrence and demand sizes:

```{r iETS}
adam(y, "MNN", occurrence=omETS, h=10, holdout=TRUE, silent=FALSE)
```


## om(): ARIMA occurrence model

Any ADAM-supported ARIMA structure can drive the occurrence dynamics. Set `model="NNN"` to suppress ETS components and specify the ARIMA orders directly. Note that automatic ARIMA order selection requires using `auto.om()` (see below) or passing `orders=list(ar=..., i=..., ma=..., select=TRUE)`:

```{r arima}
omARIMA <- om(y, model="NNN",
              orders=list(ar=1, i=0, ma=1),
              occurrence="odds-ratio", h=10, holdout=TRUE)
omARIMA
plot(omARIMA, 7)
```


## om(): Regression occurrence model

External regressors are incorporated via `cbind()`, exactly as in `adam()`. The first column of the matrix is treated as the response; subsequent columns become regressors. Here we use the `Seatbelts` dataset from the `datasets` package: the response is a binary indicator for above-median driver casualties, and the predictor is the seatbelt law indicator:

```{r regression}
data(Seatbelts)
highDeaths <- as.integer(Seatbelts[, "DriversKilled"] > median(Seatbelts[, "DriversKilled"]))
ySeat <- ts(cbind(highDeaths, law=Seatbelts[, "law"]), start=c(1969, 1), frequency=12)
omReg <- om(ySeat, model="NNN",
            occurrence="odds-ratio", regressors="use",
            h=12, holdout=TRUE)
omReg
plot(omReg, 7)
```

Setting `regressors="select"` would apply automatic variable selection, dropping regressors that do not improve the information criterion.


## omg(): the general two-component occurrence model

`omg()` fits the iETS$_G$ model directly, estimating separate ETS (or ARIMA, or regression) structures for both the $a_t$ (numerator) and $b_t$ (denominator) components of the probability link. Unlike `om(..., occurrence="general")`, which applies the same model to both sides, `omg()` lets you specify different model types for each:

```{r omg}
omgModel <- omg(y, modelA="MNN", modelB="ANN", h=10, holdout=TRUE)
omgModel
plot(omgModel, 7)
```

Calling `om(..., occurrence="general")` is a shortcut that delegates to `omg()` with the same model specification on both sides.


## auto.om(): automatic occurrence type selection

`auto.om()` fits `om()` (or `omg()`) for each candidate occurrence type and returns the model with the lowest information criterion. By default all five types are tested:

```{r autoOmAll}
autoOmModel <- auto.om(y, model="MNN", h=10, holdout=TRUE)
autoOmModel
```

Passing `orders=list(ar=2, i=1, ma=2, select=TRUE)` activates automatic ARIMA order selection for each candidate occurrence type, returning the best overall combination of occurrence link and ARIMA structure:

```{r autoOmARIMA}
autoOmARIMA <- auto.om(y, model="MNN",
                       orders=list(ar=2, i=1, ma=2, select=TRUE),
                       h=10, holdout=TRUE)
autoOmARIMA
```

A subset of occurrence types can be tested by supplying an explicit vector:

```{r autoOmSubset}
autoOmSubset <- auto.om(y, model="MNN",
                        occurrence=c("fixed", "odds-ratio", "inverse-odds-ratio"),
                        h=10, holdout=TRUE)
autoOmSubset
```


## See also

The oETS model family and its mathematical foundations are documented in detail in the [oes vignette](oes.html). The `oes()` function provides these same oETS models with a simpler, ETS-only interface. For the full intermittent demand model that combines occurrence and demand sizes, use `adam()` with the estimated occurrence model passed to the `occurrence` argument.

## References
